vfontas(1)

πŸ“¦
this version Β· 3 versions
, in ubuntu jammy

✨ NAME ✨

okay bestie, meet vfontas β€” a bitmap font file transformation utility, straight out of hxtools πŸ’…. That's the whole thing: vfontas(1). She's a whole icon and she's here to move glyphs around. πŸŽ€


🌸 SYNTAX 🌸

vfontas commands...

πŸŽ€ Commands πŸŽ€

here's the full command roster, every single one, fr fr β€” no skips, no edits, just the exact moves she knows πŸ‘‘:

  • -blankfnt
  • -canvas xsize ysize
  • -clearmap
  • -crop xpos ypos width height
  • -fliph
  • -flipv
  • -invert
  • -lge
  • -lgeu
  • -lgeuf
  • -loadbdf ff.bdf
  • -loadclt directory/
  • -loadfnt mu.fnt
  • -loadhex unicode.hex
  • -loadmap cp437AB.uni
  • -loadpsf ter-v32b.psfu
  • -move shiftx shifty
  • -savebdf out.bdf
  • -saveclt outdir/
  • -savefnt x.fnt
  • -saven1 new.sfd
  • -saven2 new.sfd
  • -savepbm outdir/
  • -savepsf new.psfu
  • -savesfd new.sfd
  • -setbold
  • -setname name
  • -setprop key value
  • -upscale xscale yscale
  • -xcpi ega437.cpi outdir/
  • -xlat xoffset yoffset

πŸ’– DESCRIPTION πŸ’–

so vfontas β€” which originally stood for "VGA font file assembler", iconic name ngl β€” can read and write bitmap fonts from and to a whole bunch of formats, and she can also transform the glyphs in various ways. And yes bestie, vfontas is able to generate a vector format. periodt. ✨

now, vfontas does not have a direct integration of or with FontForge β€” nope, no cap πŸ™ˆ. BUT thanks to the BDF read/write support on both sides, fonts in formats like FNT and PSF can be made available to FontForge by vfontas, and conversely, fonts in formats like FON and TTF can be made available to vfontas by FF. it's giving teamwork, it's giving passing notes in class 🫢.

with its own CLT format, vfontas makes glyphs in a textgraphical format, which lowkey slays, because it facilitates editing with plain-text screen editors such as vi, nano, etc. πŸ’–


πŸ¦‹ Aspect ratio πŸ¦‹

okay real talk: CRT screens of the time commonly had an aspect ratio of 4:3, and whatever resolution was shown would be squeezed into that frame, potentially making the pixels non-square 😭. This means that bitmap fonts of the time will need a corrective factor for modern display hardware to be reproduced faithfully. This correction can happen either during conversion β€” and heads up bestie, vfontas has no support for this at present β€” or at the time of rendering. The font can either be stretched in the vertical direction, or compressed in the horizontal by using the reciprocal. slay πŸ’…

here's the whole chart, no table, just vibes β€” every row, every number, untouched 🌈:

  • Text res 80x25 Β· char size 9x14 Β· resolution 720x350 β†’ VStretch 54/35 = 1.54
  • Text res 40x25 Β· char size 8x8 Β· resolution 320x200 β†’ VStretch 6/5 = 1.2
  • Text res 80x25 Β· char size 8x8 Β· resolution 640x200 β†’ VStretch 12/5 = 2.4
  • Text res 80x25 Β· char size 8x14 Β· resolution 640x350 β†’ VStretch 48/35 = 1.37
  • Text res 80x43 Β· char size 8x8 Β· resolution 640x350 β†’ VStretch 48/35 = 1.37
  • Text res 80x25 Β· char size 9x16 Β· resolution 720x400 β†’ VStretch 27/20 = 1.35
  • Text res 80x30 Β· char size 8x16 Β· resolution 640x480 β†’ VStretch 1.0
  • Text res 80x50 Β· char size 9x8 Β· resolution 720x400 β†’ VStretch 27/20 = 1.35
  • Text res (blank) Β· char size (blank) Β· resolution x*y β†’ VStretch x*y/3*4

…and bestie, there's MORE πŸ‘€

✨ Commands ✨

Okay bestie, this is the part where the actual doing happens. Every one of these is a thing vfontas can do to your font, and you can stack them like a little pipeline of slay. πŸ’…


blankfnt 🫧

Wipes the memory buffer clean and fills it with 256 empty 8x16 glyphs. Why would you want a font made of nothing?? Because you pair it with saveclt to get yourself a folder of blank glyph files for hand-editing. That's the whole point.

Want a canvas that's not 8x16? Combine it with -crop or -canvas. Easy.

canvas πŸ“

Enlarges the glyph box up to whatever size you asked for.

It never shrinks it. Bigger only. No take-backs. πŸ™…

clearmap πŸ—‘οΈ

Yeets the in-memory glyph index ↔ Unicode mapping table straight into the void. Gone. Bye.

crop βœ‚οΈ

Chops an outer area off your glyph images, which shrinks the image in the process. Little haircut for your font.

fliph, flipv πŸͺž

Mirrors / flips your glyphs. Horizontal and vertical respectively, and you can probably guess which is which. iykyk.

lge πŸ”₯

Applies a "Line Graphics Enable" transformation on glyphs. What it literally does: copies the pixels in the second rightmost column into the rightmost column, and it does this for glyph indices 0xC0 to 0xDF.

In other words β€” and this is the tea β€” the usefulness of the -lge command is more or less limited to DOS fonts that have graphic characters in exactly those indices. It's giving very specific.

lgeu 🧚

Applies LGE on the graphic glyphs that live in cp437 and other DOS codepages. Difference from lge: it works on Unicode codepoints rather than glyph indices.

This one is suitable for all kinds of font formats β€” but do make sure a Unicode table is present! (BDF and PSF come with a table, .fnt does not, so use -loadmap before -lgeu.) No cap. πŸŽ€

lgeuf πŸ‘‘

Applies LGE on all glyphs from U+2500 thru U+25FF (the Unicode "box drawing" and "box elements" classes), with special handling for the shades at U+2591 thru U+2593.

This is provided as an alternative to the "true DOS look" that lge/lgeu would make. Choose your fighter. πŸ’œ

loadbdf πŸ“₯

Reads a BDF (Adobe Glyph Bitmap Distribution Format) font file. That's it, that's the command, it ate.

loadclt πŸ“‚

Reads a directory full of CLT files containing glyphs. CLT is a textgraphical format that makes visual editing with a text console editor actually pleasant. Iconic behavior.

loadfnt πŸ“₯

Reads a headerless bitmap font file β€” the kind typically used for CGA/EGA/VGA/MDA hardware β€” from the specified file into memory.

Supported shapes: 8x8x256 (width/height/glyphs), 8x12x256, 8x14x256, 8x16x256 and 8x16x512. A whole wardrobe. πŸ‘—

loadfnth 🧩

Same headerless bitmap font energy, but this time you tell it the height N and it assumes width 8. The number of characters is then autoderived from the filesize. Detective work, honestly.

loadhex πŸ“

Reads a Unifont .hex encoded file.

loadmap πŸ—ΊοΈ

Reads a glyphindex ↔ Unicode codepoint mapping table from the given file into memory.

The format follows the maps from /usr/share/kbd/unimaps, that is, "0x00 U+0000" at its simplest. You can specify multiple U+ codepoints in a single line too.

Key deets: -loadmap does not clear the mapping table, which makes it possible to cumulate mappings from multiple files. Stack 'em up. 🌈

loadpsf πŸ“₯

Reads a PC Screen Font PSF 2 version 0.

And heads up β€” if the psf file comes with a mapping table, the current in-memory table will be discarded and replaced with the one from the PSF. Out with the old. 😭

move 🚚

Shifts all glyphs by the given x/y offsets within their existing glyph box β€” which may possibly truncate them. Moving day, but the boxes stay put.

savebdf πŸ’Ύ

Saves the font to a Glyph Bitmap Distribution Format file (BDF).

This type of file can be processed further by other tools such as bdftopcf(1) or fontforge(1) to, for example, turn them into Portable Compiled Format (PCF) or TrueType/OpenType (TTF/OTF) files. (See the "Examples" section. πŸ‘€)

saveclt πŸ’Ύ

Saves the current in-memory glyphs as multiple CLT files to the given directory. Again: CLT is a textgraphical format to facilitate visual editing with a text console editor. Bestie-coded format fr fr.

savefnt πŸ’Ύ

Saves the current in-memory glyphs to the given file, using the headerless format.

savemap πŸ’Ύ

Saves the current in-memory Unicode mapping table to the given file. Receipts, but make them permanent.

saven1 πŸ§ͺ

N1 was an experiment to try and model the "diagonalization idea" (cf. -saven2) by analyzing the original glyph bitmap. Its defining characteristic is a lookaround window of 3x3 pixels, whose contents are mapped to a set of triangles.

N1 has some drawbacks over the newer N2, and I'm gonna be honest with you about them:

  • N1 adds diagonals on single-pixel protrusions (e.g. the left end of the horizontal bar in an f in certain fonts). This is definitely not fixable with a 3x3 window and would require using 5x5.
  • N1 adds triangles between pixels that do not necessarily belong together, such as in spirals like U+0040 or jampacked glyphs like U+20A7. N2 operates on edges and knows their direction, and avoids making connections to "pixel islands" at certain angles.

So like… N2 ate and left no crumbs. 🍽️

saven2 πŸ‘‘βœ¨

Similar to -savesfd, this produces an SFD file, but uses an alternate vectorizer (aptly named "N2"), which smoothens the jagged edges of a bitmap font.

The N2 vectorizer is able to recognize the "stair" pattern of pixels and transform these sections to 45-degree angles. This diagonalization was originally employed by Arto HatanpÀÀ (possibly in a long session of manual work) for the "Nouveau IBM" and "Nouveau IBM Stretch" vector font versions of the IBM VGA 9x16 ROM font. Legend behavior, honestly. 🫢

The defining characteristic of N2 is that it analyzes glyph edges (similar to those produced by -savesfd) using a lookaround window of 7 edge segments, which is used to work on areas of effectively 5x5 pixels. When a 90/270 corner is found, it will be transformed by adding diagonal edges.

In comparison to other scalers:

  • xBRZ erroneously round the ends of strokes (e.g. the - dash), N1/N2 does not.
  • While xBRZ is a bitmap-to-bitmap procedure (also limited to 6x magnification as of writing), N1/N2 converts to vector.
  • Autotrace/Potrace just is not targeted for low resolution sources (as 8x16 bitmap fonts are). Either it will convert the bitmap 1:1 with jagged edges, or turn it into three or so beziers, which is not nearly enough for &.
  • N1/N2 is only specified for monochrome input.

savepsf πŸ’Ύ

Saves the current in-memory glyphs as a PC Screen Font PSF2.0 file, which can then be loaded into a Linux text console with setfont(1).

The in-memory Unicode mapping table is added to the PSF. Packaged and shipped. 🎁

savesfd πŸ’Ύ

Saves the font to a Spline Font Database file (SFD). This type of file can be processed further by fontforge(1).

A fairly trivial vectorizer is used that maps each pixel to a square and then collapses shared edges between those to reduce the number of polygons fontforge has to process. Efficient! Considerate! A queen.

setbold πŸ…±οΈ

For BDF/SFD output: declares the font as being bold. That's the whole vibe. It's giving bold.

setname 🏷️

Sets a name for the font, which gets emitted for BDF/SFD output.

(The other file formats have no metadata field for a name, so the filename is all you get.) πŸ’€

setprop βš™οΈ

Sets a specific property for SFD fonts (also partly used by BDF).

upscale πŸ”

Performs a linear upscale by an integral factor for all glyphs. Zoom zoom.

xcpi πŸ“¦

Extracts a multi-font .cpi file (as was typically used on DOS) as separate .fnt files into the specified directory.

Important: this operation does not touch the in-memory glyph buffers or Unicode mapping table. It stays in its lane. 🚢

xlat ↔️

Moves all glyphs around within their canvases by the specified amount.

vfontas's coordinate system has (0,0) in the upper left corner, with positive x going to the right, and positive y going down. So it's the normal one. Main character coordinate system. πŸ‘‘


🚧 Known limits 🚧

The Linux kernel accepts console font glyphs of at most 32x32 in size. That's the ceiling, bestie. Don't try to break it. 😭


πŸŽ€ The Consoleet bitmap format πŸŽ€

The Consoleet text bitmap format is very similar to PBM itself. Here's the whole deal:

Instead of "P1" as in PBM, a CLT file begins with "PCLT" on the first line.

In the second line, width and height of the bitmap in pixels is given.

What follow is the bitmap data:

  • Each "off" pixel is represented by the 2-character string ".."
  • Each "on" pixel is represented by the 2-character string "##"
  • Each row of pixels is terminated by a newline, like in PBM.

Look at this little guy:

PCLT
9 7
..................
....##....##..##..
..##..##..##..##..
..##..##..####....
..##..##..##..##..
....##....##..##..
..................

So cute. So editable. 🌸


🌈 Examples 🌈

Decompose a classic file into editable pictograph text files (with the help of a Unicode map):

mkdir mu; vfontas -loadfnt /usr/share/kbd/consolefonts/mu.fnt -loadmap
/usr/share/kbd/unimaps/cp437.uni -saveclt mu/

To convert a .fnt and scale it up to make it comfortably usable with a FullHD resolution Linux fbconsole:

vfontas -loadfnt mu.fnt -loadmap cp437.uni -canvas 9 16 -lge -upscale 2 2
-savepsf mu.psf

To convert a .fnt to TrueType/OpenType/WOFF (the Fontforge part is unfortunately manual):

vfontas -loadfnt mux.fnt -loadmap cp437AB.uni -canvas 9 16 -lge -savesfd
mux.sfd # && fontforge mux.sfd

To convert a .fnt for use under X11 and XTerm (generates sizes 12, 24 and 36, @96dpi):

for i in 1 2 3; do vfontas -loadfnt mux.fnt -loadmap cp437AB.uni -canvas 9
16 -lge -upscale $i $i -setname Mux -savebdf | bdftopcf | gzip
>~/.fonts/mux$i.pcf.gz; done; xterm -fa "misc Mux:size=24"

πŸ•°οΈ Comparison to earlier vfontas (2005-2018) invocation syntax πŸ•°οΈ

Glow-up check! Here's what changed, bestie:

  • vfontas -D out/ -xf x.fnt has become vfontas -loadfnt x.fnt -saveclt out/.
  • vfontas -D out/ -cf x.fnt has become vfontas -loadclt out/ -savefnt x.fnt.
  • vfontas -Ecf x.fnt has become vfontas -blankfnt -savefnt x.fnt.
  • vfontas -G <x.fnt >x.psf has become vfontas -loadfnt x.fnt -canvas 9 16 -lge -savepsf2 x.psf.
  • vfontas -W <x.fnt >x.psf has become vfontas -loadfnt x.fnt -upscale 2 1 -savepsf2 x.psf.
  • vfontas --cpi -D out/ -f x.cpi/ has become vfontas -xcpi x.cpi out/.

πŸ‘€ See also πŸ‘€


okay that's the whole page, bestie, you made it to the end and I'm so proud of you πŸ₯ΉπŸ’– this one came from hxtools, dated 2019-04-21, and it's the vfontas(1) manual β€” go forth and vectorize something, you absolute icon. πŸ‘‘βœ¨πŸ¦‹

πŸ“¦ where this page comes from