I just created a new font using fontforge. It's a 11x11 font designed for playing roguelikes without x/y distortion and without straining my eyes with FreeBSD's included 8x8 font. How can I convert it to the .fnt format that vt accepts?
I have successfully converted BDF fonts that are 12 pixels wide. I would guess that 11 pixels should work too – If there were any restrictions, they should be mentioned in the manual page. Maybe something else is wrong or non-standard with your font? Are you sure it is a mono-space font? I don't think proportional fonts are handled correctly.Does anyone know which widths are supported? I tried 10 and it doesn't work either. If -w is specified. vtfontcvt won't complain and will generate the file, but vt fails to render it properly. It looks as if there is no gravity on the tty, lowercase letters float straight to the top of the line. I'll be damned if vt only supports widths that are a multiple of 8. That leaves me stuck with 8x8 only, since 16 is too wide.
I have successfully converted BDF fonts that are 12 pixels wide. I would guess that 11 pixels should work too – If there were any restrictions, they should be mentioned in the manual page. Maybe something else is wrong or non-standard with your font? Are you sure it is a mono-space font? I don't think proportional fonts are handled correctly.
deadcatco% ls diesel:~/docs/digitaldevil
DD.sfd digitaldevil-11.bdf
deadcatco% vtfontcvt digitaldevil-11.bdf digitaldevil.fnt
vtfontcvt: Bitmap with unsupported width 11!
deadcatco% ls :( diesel:~/docs/digitaldevil
DD.sfd digitaldevil-11.bdf
deadcatco% vtfontcvt -v -w 11 -h 11 digitaldevil-11.bdf digitaldevil.fnt
Statistics:
- glyph_total: 234
- glyph_normal: 234
- glyph_normal_right: 0
- glyph_bold: 0
- glyph_bold_right: 0
- glyph_unique: 105
- glyph_dupe: 129
- mapping_total: 234
- mapping_normal: 234
- mapping_normal_folded: 142
- mapping_normal_right: 0
- mapping_normal_right_folded: 0
- mapping_bold: 0
- mapping_bold_folded: 0
- mapping_bold_right: 0
- mapping_bold_right_folded: 0
- mapping_unique: 234
- mapping_dupe: 0
deadcatco% ls diesel:~/docs/digitaldevil
DD.sfd digitaldevil-11.bdf digitaldevil.fnt
Well, the font that I used doesn't have unused space; the bounding boxes of all characters are the same. The empty spaces are just filled with “0” bits. I wrote a very simple BDF font editor that only supports such a simplified variant of BDF font. I guess that vtfontcvf does not support the complete BDF standard, but only a subset. So, maybe your font uses features that are technically correct, but not supported by vtfontvft. But that's just a guess; I haven't studied the code.[…]The main problem I noticed is that the empty space on top of glyphs that don't go all the way up. such as lowercase letters, is rendered below them instead, which makes them appear as floating.
vtfontcvt, only after commenting out the
if (spc != 'c' && spc != 'C')
errx(1, "font spacing \"C\" (character cell) required");
psf2bdf --iso10646 --fontname=name source_file result_file; otherwise the error happened, on out-of-the-box vtfontcvt and vtfontcvt-ng alike. The problem does not affect bdf files made by pcf2bdf(1). font spacing "C" (character cell) required error. bitmap with unsupported DWIDTH PIO_FONT: Invalid argument FONTBOUNDINGBOX <fbbw> has to match all the DWIDTH <dwidth> lines below (or x2 according to source, but we'll put that aside). This will require some hand-tuning because if you change fbbw to match dwidth the characters will be scrunched; and if you change dwidth to match fbbw, then your characters will be spaced too far apart. Anyway the important thing is that they match. STARTCHAR might be descriptive or not (IBMPlexMono has it as ydieresis), but just delete all of the remaining chars while leaving the final ENDFONT line in place. FONT line ensure that SPACING as per X logical font description is 'C'. And also ensure that the line that explicitly states SPACING matches with a corresponding 'C'. $ vtfontcvt-ng IBMPlexMono/IBMPlexMono-14.bdf fnt/IBMPlexMono-14.fnt
$ sudo cp fnt/*.fnt /usr/share/vt/fonts
$ sudo vidcontrol -f /usr/share/vt/fonts/IBMPlexMono-14.fnt # While in vt, and not X-DWIDTH 8 0 for all glyphs, which certainly is what you need for an 8x16 font.ENCODING value of -1... all in all, no way to feed that to vtfontcvt(8). So, I decided to write myself a very quick and dirty tool converting this mess to "unifont hex" format first, rendering all the glyphs into 8x16 cells (and the few ones that are too wide into 16x16 cells, although I don't know whether vt(4) actually displays them correctly):#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char linebuf[128];
uint8_t bitmap[32][2];
int encoding, w, h, x, y, bmr;
int main(int argc, char **argv)
{
FILE *bdf = 0;
int rc = 1;
if (argc != 2 || !(bdf = fopen(argv[1], "r")))
{
fputs("Usage: bdf2hex font.bdf\n", stderr);
goto done;
}
bmr = -1;
while (fgets(linebuf, sizeof linebuf, bdf))
{
if (bmr >= 0)
{
if (!strncmp(linebuf, "ENDCHAR", 7))
{
bmr = -1;
if (encoding > 0 && encoding < 0x10000)
{
printf("%04X:", (unsigned)encoding);
y += 4;
int sy = 0;
while (h > 16 && y > h) {--y; ++sy; --h;}
for (int r = 0; r < 16; ++r)
{
if (r < 16-(h+y) || sy >= h)
{
fputs(w>8?"0000":"00", stdout);
continue;
}
if (w > 8)
{
uint8_t a = bitmap[sy][0];
uint8_t b = bitmap[sy][1];
for (int sx = x; sx > 0; --sx)
{
uint8_t c = (a&1)<<7;
a >>= 1;
b >>= 1;
b |= c;
}
printf("%02hhX%02hhX", a, b);
}
else printf("%02hhX", (uint8_t)(bitmap[sy][0]>>x));
++sy;
}
fputs("\n", stdout);
rc = 0;
}
}
else
{
uint8_t v;
if (sscanf(linebuf, "%02hhX", &v) > 0) bitmap[bmr][0] = v;
if (sscanf(linebuf+2, "%02hhX", &v) > 0) bitmap[bmr][1] = v;
++bmr;
}
continue;
}
if (!strncmp(linebuf, "ENCODING ", 9))
{
encoding = atoi(linebuf+9);
}
else if (!strncmp(linebuf, "BBX ", 4))
{
sscanf(linebuf+4, "%d %d %d %d", &w, &h, &x, &y);
}
else if (!strncmp(linebuf, "BITMAP", 6))
{
memset(bitmap, 0, sizeof bitmap);
bmr = 0;
}
}
done:
if (bdf) fclose(bdf);
return rc;
}
How do I use this program ?This has sparked my interest, why not try and get my preferred font (MS' "Consolas") displayed on the vt(4) console as well?
Spoiler, it works but looks quite crappy rasterized to 8x16 cells -- oh well ?
I started as described using fontforge to create a rasterized version in BDF format. By trial and error, I found I need to specify a pixel size of 15 to end up with a font that hasDWIDTH 8 0for all glyphs, which certainly is what you need for an 8x16 font.
But then, some glyphs are wider than 8 pixels, and some have really excessive over- and underlengths not fitting into 16 rows, and the result even contained quite some glyphs with an invalidENCODINGvalue of-1... all in all, no way to feed that to vtfontcvt(8). So, I decided to write myself a very quick and dirty tool converting this mess to "unifont hex" format first, rendering all the glyphs into 8x16 cells (and the few ones that are too wide into 16x16 cells, although I don't know whether vt(4) actually displays them correctly):
C:#include <stdint.h> #include <stdio.h> #include <stdlib.h> #include <string.h> char linebuf[128]; uint8_t bitmap[32][2]; int encoding, w, h, x, y, bmr; int main(int argc, char **argv) { FILE *bdf = 0; int rc = 1; if (argc != 2 || !(bdf = fopen(argv[1], "r"))) { fputs("Usage: bdf2hex font.bdf\n", stderr); goto done; } bmr = -1; while (fgets(linebuf, sizeof linebuf, bdf)) { if (bmr >= 0) { if (!strncmp(linebuf, "ENDCHAR", 7)) { bmr = -1; if (encoding > 0 && encoding < 0x10000) { printf("%04X:", (unsigned)encoding); y += 4; int sy = 0; while (h > 16 && y > h) {--y; ++sy; --h;} for (int r = 0; r < 16; ++r) { if (r < 16-(h+y) || sy >= h) { fputs(w>8?"0000":"00", stdout); continue; } if (w > 8) { uint8_t a = bitmap[sy][0]; uint8_t b = bitmap[sy][1]; for (int sx = x; sx > 0; --sx) { uint8_t c = (a&1)<<7; a >>= 1; b >>= 1; b |= c; } printf("%02hhX%02hhX", a, b); } else printf("%02hhX", (uint8_t)(bitmap[sy][0]>>x)); ++sy; } fputs("\n", stdout); rc = 0; } } else { uint8_t v; if (sscanf(linebuf, "%02hhX", &v) > 0) bitmap[bmr][0] = v; if (sscanf(linebuf+2, "%02hhX", &v) > 0) bitmap[bmr][1] = v; ++bmr; } continue; } if (!strncmp(linebuf, "ENCODING ", 9)) { encoding = atoi(linebuf+9); } else if (!strncmp(linebuf, "BBX ", 4)) { sscanf(linebuf+4, "%d %d %d %d", &w, &h, &x, &y); } else if (!strncmp(linebuf, "BITMAP", 6)) { memset(bitmap, 0, sizeof bitmap); bmr = 0; } } done: if (bdf) fclose(bdf); return rc; }
Note this tool hardcodes a lot of things (like the target size of 8x16 or 16x16, a fixed y-shift of 4 rows, ...) and also does close to no input validation and error handling. So, use with care and modify as needed
For me, vtfontcvt(8) converted the resulting hex format perfectly fine!