Texture Healing for Monospace Fonts
github.com
github.com
Maybe my brain would adjust after a while. And maybe I'm also different to other people. I think my reading skills are a bit skewed towards recognizing words/patterns instead of reading characters (probably some form of compensation for my dyslexia).
Take a look at the code editor examples on the main site for Github Monaspace: https://monaspace.githubnext.com Scroll down to the "Five Fonts" section and try unchecking the texture healing toggle.
The fisheye effect you get when looking at the font in 200pt goes away at 16pt, and in the context of a busy code block, has the effect of smoothing out the visual rhythm of the characters with only a minor disruption of the monospace grid. Perhaps it's not for everyone (it is a trade-off), but I think it's a smart compromise.
One question people sometimes ask is, "How can you code in a proportional font? How do you line things up in columns?"
The answer is you don't. For example, the Black code formatter for Python completely eschews column alignment of this sort:
foo.bar(one,
two,
three)
(Imagine that the words were long enough that the whole thing wouldn't fit on one line.)Instead, Black formats it like this:
foo.bar(
one,
two,
three
)
No column alignment, only indentation. Code formatted like this is equally readable in a proportional or monospaced font. You don't need monospaced fonts!I've read and written all my code in proportional fonts for close to 20 years. My current one is Trebuchet++, a variant of Trebuchet MS that I customized in FontForge.
Trebuchet MS is pretty good on its own. For example, all of the "confusable" glyphs are easy to distinguish. And it renders very nicely on a high-DPI display.
Its tilde is pretty bad, though. It's tiny and almost looks like a hyphen. So that was the first thing I fixed, putting in a better tilde.
Then I experimented with spacing for the _ and . glyphs. I added negative margin on both sides of the _, while keeping its width. And I added positive spacing on both sides of the . glyph. Consider code like this:
snake_case_name.another_snaky_name()
These spacing changes have the affect of pulling the individual words in each name closer together, while increasing the separation between the two names.
It is subtle, but to my eye it helps readability.
Next up will be to add some positive margin inside the three pairs of brackety things: (), [], {}. I have always found that it helps readability to add a space inside parens and such, but most contemporary code formatters prohibit this. With a proportional font I can tweak the font to put some visual spacing there.
Thanks, but no. Your foo.bar() example is significantly less readable the way Black formats it.
what, how? Wouldn't the number of spaces you'd need to prefix lines 2 and 3 with vary between fonts?
foo.bar(one
two,
three) //this is fine, and slight drift on different fonts is also fine
I would have demonstrated in a proper proportional way but HN destroys NBSP.My argument is that both fonts are just as good in this situation, and monospaced fonts aren't benefiting here. You don't need monospaced fonts to use formatting 1, you can just choose formatting 1 and then use either kind of font.
Doesn't that mean I disagree with your post?
It's important to note that I'm not comparing monospace versus proportional. I'm saying that "formatting 1 with proportional font" isn't really worse than "formatting 2 with proportional font". Both of them are going to have problems from someone that really likes monospacing.
"If you already decided to have a proportional font, you don't need to stop doing any things."
My argument is that "need to stop doing X" is not true for either kind of font.
I suspect the state where different width variants of the same letter are close to each other would happen a lot more in the real world.
const timing_end_m_ = () => {
let timing_end = new Date();
let time_spent = timing_end - timing_start; // in msThe fact that the "i" in "terminal dimensions" and the "i" in "width" aren't underneath each other makes it look like my monitor is broken or something. It's like someone has done it on purpose to mess with me.
I'll stick to the consistent design for a slightly less aesthetic experience for that reason alone.
Interestingly enough, the fact that letterforms change as I type doesn't bother me the way I thought it would -- turns out I'm already kinda used to it from ligatures.
So points for being a clever idea to try out, but unfortunately what it does to a word like "gimme" just makes it a non-starter. Let's face it -- lowercase m's in monospace will always be ugly and cramped, but at least they're consistently so.
It's not like this is limited to just a few pairs of letters like 'mi', or just pairs - if you've seen Fontemon https://www.coderelay.io/fontemon.html you know the sky is the limit for what the rewrites can do!
The same letterform having different widths just looks bad and wrong.
It's not like kerning, which always looks good when done well (for proportional fonts).
In "gimme" you could have a rule that when any character is next to itself both occurrences must have the same width. Wouldn't that fix the "gimme" example?
Everything else would just look like a proportional font.
Maybe it would influence coders too much and subconsciously make them choose names that line up well though...
1) Horizontal spacing needs to align vertically between glyphs of the same letters on separate lines. This is the example I give elsewhere of a letter "i" being in a very slightly different position than the same letter just two lines above it. I personally find this extremely disturbing and unpleasant to look at in monospace.
2) The glyph of a letter needs to be the exact same between instances of the same letter that are in any kind of visual proximity. This is the "gimme" example the parent of your comment gives. AnyThinG ElSe LoOkS lIkE jumblycase. Which I think we can all agree is just plain horrible.
It might be nice for reading code, but for editing code it feels weird that glyphs change their size while you type.
Also readability wise I'm not convinced. In the example there is a combination like "_m_", in this case the lette m is much nicer to read. But then i typed "mml", which makes the two m's very different looking. Also the line number 10 on top of 11 looks weird.
Applying display typography techniques to code is an objectively bad idea for both reading and writing.
They even enable ligatures by default on the demo which is far worse. For those of us who actually have to get work done and not just fetishize code and fawn over aesthetics, it's a fundamental requirement that every single character be as unambiguous and consistent as possible.
In human to human communication those changes don't necessarily apply. Even the politicians that are most violent with their words in speeches are often completely "normal" once the cameras are turned off.
I'm not misusing these words for hyperbole. We're talking about text. Words like "literal" and "objective" belong here. At this stage of the game, few subjective decisions are left to tinker with in programming. I'm sorry if that sort of thing brings you joy. Get another hobby.
It's objectively bad to alter the visual presentation of font glyphs for non-functional purposes. If a programmer sees the same glyph with varying width, they have to wonder if it's the same underlying character. If a ligature is applied, they have to wonder if it's the same character being displayed. That's a huge waste of time for little to no benefit. We are very far away from these concerns being a thing of the past. The cognitive load must still sometimes fall back on human inspection. A cute font shouldn't prevent you from doing that, nor should anyone need to break out the hex editor to be sure. This simple knowledge cannot die off into obscurity yet.
If y'all want pretty code it must be done at the text encoding and compiler level (invent a new keyboard layout while you're at it!), not in the fonts... but that too would just repeat the sins of the past. :)
Agreed. I find this even more noticeable and distracting with narrow characters; e.g. in “llm”, one of the “l”s reads like “1” to me.
Another variation on that theme are “duospace fonts”, like iA Writer Duo [1]. Those use two character widths instead of one (i.e. wide characters are always 1.5x wider than narrow). I think this could work for code, too.
[1]: https://ia.net/topics/in-search-of-the-perfect-writing-font
“Most of the type set in the past five hundred years is justified type, and most of it has been justified line by line, by the simple expedient of altering the space between the words. There are, however, better ways. Scribes justify text as they write by introducing abbreviations and subtly altering the widths of letters. Gutenberg replicated the feat by cutting and casting a host of abbreviations and ligatures along with multiple versions of certain letters differing modestly in width. In the early 1990s, Peter Karow and Hermann Zapf devised a means of doing much the same in the digital medium[.] [...] Another thing computer software can do – because Karow taught it how – is justify text by making subtle alterations in the spaces within letters as well as those between letters and words.”
The Elements of Typographic Style, fourth edition, by Robert Bringhurst, pp 191–192.
I have an idea for an advanced technique that yields much better visual appearance (but that is also not want you'd want, for the same reasons): instead of just focussing on pairs of letters (so primitive!), consider whole words and optimise their letters' shape, width, and horizontal position, but keep the size of box of the word. I call that 'equilibrium texture healing'.
Is that just a poorly drawn/incorrect example graphic?
[0] https://github.com/githubnext/monaspace/blob/main/docs/Textu...
Perceptually, based only on playing with it a minute, it seems to improve legibility a bit (but not as much as a proportional font would be) but also visually breaks the alignment a little sometimes.
Not sure it's a worthwhile overall, but interesting.
Things people here seem to misunderstand:
1. The grid is not affected. The resp. letters stay within their grid-aligned bounding boxes.
2. Letters may change while you type but this is not noticeable in practice. I have a 3.2x2k 15" screen on my laptop. At my editor's effective font size of around 20px (capital letters, from baseline to top) the change in shape is about a pixel for something like the letter 'm'.
Caveat: I'm an ex-typographer. As such I not only do care way more about these things than the average engineer. I'm also more aware that these things do have an effect on eye/brain/visual system strain that is possibly very hard to quantify.
But legibility of a text is a thing. And the font with its properties is one very important factor (font width/kerning/line height are equally important in that regard -- nevertheless).
Edit: typos
So it's not only readability, but also "comparability".
Their own examples literally show that this isn't the case. Just look at the "filming" example, with the "m". In addition, their five fonts showcase shows that letters that "need space" can overbound.
I think it's accurate to say that a word respects it's bounding box, but interior glyphs don't necessarily. Unless their own examples are somehow misrepresentative.
They don't, it's an optical illusion. That's the whole point. Read the whole text and/or open the example images which show the different versions of 'm' and 'i' side by side and measure their bounding boxes. Or open the fonts in a font editor.
They have all the same width.
Think about the implications if what you said were true. The font (or typeset engine) can't know how many pairs or triplets of these special case letter combos are in a word or a line. So you can't make sure a word stays the same width. It's impossible. There is no 'lookahead' the font designer can use to ensure this.
The only option really, to respect the grid, is staying inside equally spaced bounding boxes that are the core property of a monospaced font.
...or just making sure your immediate neighbors and yourself equal their previous total bounding box? "Needs space" glyphs borrow from "gives space" glyphs, but only in the immediate vicinity not in totality. Spaces are neutral characters.
But I don't like the font, so no real tests ;)
That's not to say it's bad at all, just that I think it wouldn't be right for how I'd mostly likely be using such a font.
Perhaps fonts are something you get used to after some time using it, but I ended up switching back to my favorite font, Input Mono (which, as a coding font, isn't actually monospace, so it brings a bunch of cool features and doesn't need to do texture healing).
Not having the glyph of a specific letter always align with itself vertically in a monospace font is just horrendous. It's so unpleasant for me to look at it makes the whole horizontal spacing thing moot.
absolutely impossible for me, so perhaps it has a use for likeminded folks.
If you use a normal stroke width (one that makes the empty space in the "m" as wide as the stroke) and width/height ratio for all characters, the problem naturally disappears, and in fact this is not a problem for instance in Linux terminals with the default fonts (normally DejaVu Sans Mono), where the characters look perfectly natural and fine.
Might as well be in this thread on the Monaspace fonts https://news.ycombinator.com/item?id=38210574
It uses SDF and looks good, just not quite angular enough at bigger zooms for me.