Friday, September 23, 2022

Prototype 5×10 Font Arrives!

Ooo... buckle up. This is a sequel to Stupid O'Clock is the Font of Stupidity.

Our sequel begins where the math was grokked. To wit:
For those, I can bring the terminal screen to use the full extent of the 1920 horizontal pixels. Easy. And without going that far, Vim has no text decoration that eats up cells, which gives us the full 80 characters (I refuse to use line numbers on the side of the simple reason that the ruler in my status already shows the line number of the cursor). Zipf's Law suggests that very long lines are rare, and thus as long as I can find a font for my terminal emulator to handle about 161 characters for half the screen (math says that each character needs to have about 1920/2/161=5.962 pixels), I'm gold.
That 6×11 font that I put together is displayed here:
In comparison, this is the 6×10 font of Opti Small:
Thus, the last time we ended that post, it was decided that I would stick with Opti Small because I figured that interpreting the width of 5.962 pixels as 6 pixels was good enough to support the vertical split screen with the 80-character line length limit.

Well, after nearly a week of using that set up, the answer was a resounding no.

Even a simple vertical split would leave one screen be good at showing only 79 characters for some reason, and with the word-delimiter soft-wrapping option that I use in Vim, it made everything very misleading.

Thus I had to choose the next best width, that of 5 pixels. There were, unfortunately, some problems. I mentioned in my previous post that CG Mono had some problems. Specifically, this was what I said:
It was fine, but still looked a bit off because the `>' glyph was bogus---it lacked the crispness that came from bitmap fonts, and looked like some other font was chosen to render it instead.
More specifically, this is how CG Mono looks like when it is at 7pt (or 6×10):
Notice that weirdness in the `>' glyph---I didn't do anything. All the screenshots are directly taken from whatever was rendered in mintty.

The only font that I had lying around that had 5 pixels of width was CG Mono at 6pt (or 5×9):
See, the problem with this font is that the parts where it is used most often (i.e. the characters between 0x20 to 0x7f) have instances where they are smushed into each other in the bid to preserve some of the fine detail (like the tines in `M', `w', and the like). Compare this against the sample of Opti Small above---Opti Small is so much more readable with the enforced vertical pixel of spacing.

The only problem was that Opti Small was not 5 pixels wide---it was 6.

And so, I decided to take Opti Small as the starting point, and make my own 5×10 font.

Why 5×10 and not 5×9 like the one in CG Mono? It's about the verticality (108 lines versus 120 lines) with the overall need for spacing, and the reduction of the number of dimensions of downsampling I needed to worry about (I only needed to eliminate one column of pixels as opposed to one column and one row of pixels).

The general observation here is that while the Opti Small font has each character sitting in a 6×10 cell, the actual character is designed to keep within a 5×7 grid, not counting descenders and ascenders. This means that Opti Small actually has a rough 3-pixel of whitespace that separates each line. Comparatively, CG Mono at 6pt (or 5×9) had only a 2-pixel of whitespace that separates each line. It doesn't sound like much, but at these scales, that's a huge difference between quickly deciphering what the character is from developing a headache.

Thus my real task is to approximate a 4×7 character out of the 5×7 that Opti Small uses. It was mostly quite straightforward---I followed these rules of thumb that I came up with:
  • Eliminate the third column of pixels if possible;
  • If a key feature of the glyph requires pixels in the centre, offset it such that we eliminate pixels to the left of it;
  • When in doubt, eyeball and trust what the eyeball says.
That led to this current version of my cobbled-together 5×10 font:
The eagle-eyed might ask: how did I manage to do this so fast considering that I had mentioned that I was test running the set up for the week before deciding to change things up more?

More pertinently, how did I begin with a bitmap of Opti Small that was accurate and without excessive amounts of labour?

The answer lies in FontForge, and the use of the BitmapFont section of the SFD file format. I loaded the .FON file of Opti Small into FontForge, and exported an SFD file. Then I extracted out the BitmapFont section, and wrote a simple parser in Python3 that looked out for each BDFChar command before using base64.a85decode() to decode the bitmap string and write it out in a file format that was compatible with Simon Tatham's font tools.

From that generated file, it was just a straightforward exercise in adjusting it so that it becomes a 5×10 font that I built into a .FON file, giving the result as shown above.

There are some things I'm still unhappy with this new 5×10 font, but it is mostly to do with the characters of the range 0x80 to 0xff, ranges that I rarely use. I suppose I could iteratively refine them over time.

One other thing that I forgot to mention is that in the bid to keep the vertical columns of whitespace to make individual character recognition easier, I had to decide how I was to deal with the ``high contrast'' tines that appear in glyphs like `M', `W', and the like. Using my experience of working in the text editor of the Pico-8 Fantasy Console, I've learnt of/and gotten used to the rather tiny and stylised font of the Pico-8---the idea of using thicker lines to represent implicit high-contrast vertical lines was no longer abhorrent.

And now, with a font that is 5 pixels wide, my half-screen set up permits 1920/2/5=192 characters across. It's wonderful. The ample amount of unused pixels in both the horizontal and vertical directions made reading with such a font surprisingly comfortable and no less different from reading something in Opti Small.

Will I be releasing this 5×10 font? I'm not sure. Like I said, there are still things that I need to tweak and fix. In addition, the original author of Opti Small, Nicolas Botti, left behind a little confusing bit of copyright:
Copyright: Nicolas Botti 2004. Use it, distribute it, change it.
I'm no lawyer, so I don't know how best to interpret this. I suppose it is fairly safe to release the 5×10 font, but it'll be ``when it's done'', perhaps even when I figured out how to generate a version of the font that can be directly used in the Linux terminal emulator in the desktop GUI.

Anyway, that's all I have for today. Till the next update then.

No comments: