Pixel font fun
This post is also about a topic that I dealt with at the end of last year / beginning of this year. After the topic Tixy I had a working LED matrix available. And although the Tixy animations look super cool, the question was what else I could do with them. With 16 x 16 dots shining in a number of brightnesses of different colors, I had two ideas. On the one hand, I wanted to display favicons that were just as large, on the other hand, a ticker seemed a good idea to me. Both attempts were successful and you can see the source code branches at the github repository following the links.
Display Bit Slices»
And there were already Tixy.land followers who had already been thinking about how to let writing run over the matrix. First @atesgoral had a “TIXY” lettering ran vertically, later @maettig also horizontally across the field. Here’s the forumula of the vertical example:
(t,i,x,y) => [5463,2194,2386][y+t*9&7]&1<<x-1;
The first approach was promising. In order for this to work, @atesgoral cuts the lettering in three lines, which he then pushes vertically up over the field. A line is a number that corresponds to the binary value, representing which point in the matrix is on (1) or off (0).
We see this when we convert the numbers to their binary format and read them back to front. If you look closely, you will recognize that the ones (1) result in the word TIXY.
(5463).toString(2).split('').reverse().join(''); // '1110101010101'
(2194).toString(2).split('').reverse().join(''); // '010010010001'
(2386).toString(2).split('').reverse().join(''); // '010010101001'
I would like to run text horizontally, so I have to cut the lettering not into horizontal lines but into vertical slices.
Here are a few examples of how numbers create a particular slice. First the numbers from 1 to 7. At the end also the number so that all points in a column light up, the 65535. You can also do the math and, for example, subtract 255 from this number. 255 are the top 8 points. As a result, only the lower eight points will then light up. Here is the Tixy formula for this picture.
(t,i,x,y) => [1,2,3,4,5,6,7,0,127,255,254,0,255,65535,(65535-255)][x]&1<<y;
Fonts and Conversion»
Now, however, I don’t always want to start from scratch and therefore don’t want to build my own font. That already exists. And so you can quickly find BitFontMaker2 from @pentacom, for example.
BitFontMaker2 is an easy to use tool for creating your own pixel fonts and then downloading them as a TrueType font for use on the computer.
However, depending on the license, you can also open many of the fonts from the gallery via the Copy&Edit link in the editor. From there you can download the pixel data in JSON format via Data Import/Export.
In addition to the fonts from the gallery, there are also other sources where you can find fonts in BFM2 format, e.g. on Github Gist. I took my first steps with these:
- C64esque by andraaspar
- HelvetiPixel by pentacom
- VCRFont by VCRElectronicFonts
- Minnesota by Dominik Johann as Gist
Here’s a part of the JSON to see how it looks. Basically it is just a hash map with a character definition for each ASCII code as a key, as well as the name, author and other informations about the font stored for a few other keys.
{
...
"87": [0,0,0,0,0,396,396,396,428,508,476,396,0,0,0,0],
"88": [0,0,0,0,0,204,204,120,48,120,204,204,0,0,0,0],
"89": [0,0,0,0,0,204,204,204,120,48,48,48,0,0,0,0],
"90": [0,0,0,0,0,252,192,96,48,24,12,252,0,0,0,0],
...
"name": "c64esque",
"copy": "andraaspar",
"letterspace": "64"
}
Let’s take a closer look at one letter, in our case the ”W” with the ASCII code 87. And from this we build a Tixy function that draws the letter for us.
const char2ascii = (char) => char.charCodeAt(0);
const ascii2char = (ascii) => String.fromCharCode(ascii);
char2ascii('W'); // 87
(t,i,x,y) => [0,0,0,0,0,396,396,396,428,508,476,396,0,0,0,0][y]&1<<x;
(t,i,x,y) => json["87"][y]&1<<x;
However, the letter in the JSON is cut into lines. To move it horizontally I need vertical slices. Therefore, I have to convert the letter first. I also measure the width of the letter to know after how many pixels the next letter should start.
For the letter W, the array with 16 lines becomes an array with 9 columns or slices, because after that there is only white space. And more letters could then follow directly and you can write words and entire sentences.
(t,i,x,y) => [0,0,4064,4064,1536,768,1536,4064,4064][x]&1<<y;
LED Matrix»
As written before I tried and implemented this first for my LED matrix.
You can checkout my Github Repository how I managed to light up a chinese 16x16 WS2812B LED Matrix with a Raspberry PI Zero and Node.js.
Svelte Component»
But now in the course of the blog post I have also built a Svelte component. And then you can equip them with all kinds of options and get different results.
It’s so easy to write Svelte components inside my SvelteKit blog, but I still have to find the time to isolate this one, so you can use it e.g. as custom element in your own HTML.
I’ll update this post, once done.