vfont2(5)

๐Ÿ“ฆ version 1.1.3, in nixpkgs unstable, ubuntu stonking

โœจ vfont2 โ€” the variable-size font format โœจ

okay bestie, so this is a page from the PSF Tools manual โ€” it's vfont2(5), the fifth-section one (that's "file formats", for the uninitiated ๐Ÿ’…) โ€” and she's here to explain a font file layout. strap in, it's giving very much "binary structures but make it cute" ๐ŸŽ€

๐ŸŒธ NAME ๐ŸŒธ

vfont2 โ€” variable-size font format


๐Ÿฆ‹ SYNOPSIS ๐Ÿฆ‹

/usr/lib/vfont/โˆ—

๐Ÿ’– DESCRIPTION ๐Ÿ’–

so vfont2 is lowkey an attempted glow-up of the original vfont(5) file format โ€” like, the original was cute but she had limitations, and this one is here to fix them: supporting more than 256 characters, larger characters, and Unicode. icon behavior, honestly ๐Ÿ‘‘

the header looks like this, no cap:

#define VFONT2_MAGIC0 0x27
#define VFONT2_MAGIC1 0x5b
#define VFONT2_MAGIC2 0xA4
#define VFONT2_MAGIC3 0x68

/* bits used in flags */
#define VFONT2_HAS_UNICODE_TABLE 0x01

/* max version recognized so far */
#define VFONT2_MAXVERSION 0

/* UTF8 separators */
#define VFONT2_SEPARATOR  0xFF
#define VFONT2_STARTSEQ   0xFE

struct vfont2_header {
        unsigned char magic[4];
        unsigned int version;
        unsigned int headersize;    /* offset of dispatch table */
        unsigned int flags;
        unsigned int length;        /* number of glyphs */
        unsigned int bitmap_size;   /* total number of bytes for bitmaps */
        unsigned int max_height;    /* max size of a character bitmap */
     unsigned int max_width;
};

compared to an original vfont file, the "unused" xtend field has no counterpart here โ€” she said "not me, don't know her" ๐Ÿ™ˆ. and like, if somebody ever needed to extend the header, it would be straightforward: just bump up headersize and drop the extra field(s) in. easy.


๐ŸŒˆ the dispatch table ๐ŸŒˆ

at offset headersize in the file you'll find the dispatch table (iykyk, the main character โœจ). it has length entries, and each one is 18 bytes long:

struct vfont2_dispatch {
     unsigned int addr;      /* offset of glyph from start of bitmaps */
     unsigned int size;          /* number of bytes (0 if no glyph) */
     signed short up;        /* number of rows above baseline point */
     signed short down;      /* number of rows below baseline point */
     signed short left;      /* number of columns left of baseline point */
     signed short right;     /* number of columns right of baseline point */
     signed short width;         /* logical width, used by troff */
};

the number of lines present in the bitmap is up + down. and similarly, the number of columns is left + right. math is mathing ๐Ÿงฎ

okay so here's the tea: as long as the total height and width stay positive, any of up, down, left or right can be negative ๐Ÿ’€. and that just means the baseline point is outside the character bitmap. it's giving "off-grid" and we respect it.

the logical width gets used when rendering the characters โ€” it's literally the number of pixels between one character's baseline point and the next. spacing queen ๐Ÿ“


๐Ÿซถ the bitmaps ๐Ÿซถ

the bitmaps come immediately after the dispatch table. for each character there are up + down rows, and each of those rows is (( left + right ) + 7) / 8 bytes. periodt.

if a Unicode table is present, it will immediately follow the bitmaps. it's in the same format as PSF2, which goes a lil something like:

<unicodedescription> := <uc>*<seq>*<term>
<seq> := <ss><uc><uc>*
<ss> := 0xFE
<term> := 0xFF

where <uc> is a Unicode value coded in UTF-8, and the * means "zero or more occurrences of the thing before me". standard asterisk behavior ๐Ÿ’…

the leading <uc>* part gives you the Unicode symbols that are all represented by this font position. and then the following sequences are sequences of Unicode symbols โ€” probably a symbol together with combining accents, bestie โ€” that are also represented by this font position. so many aliases, so iconic ๐Ÿ‘‘

for example!! at the font position for a capital A-ring glyph, the Unicode sequence may be:

c3 85 e2 84 ab fe 41 cc 8a ff

the first six bytes correspond to two Unicode characters (U+00C5 LATIN CAPITAL LETTER A WITH RING ABOVE and U+212B ANGSTROM SIGN). then 0xfe acts as a separator, and the next three bytes correspond to the two Unicode characters U+0041 LATIN CAPITAL LETTER A and U+030A COMBINING RING ABOVE. truly a serve ๐ŸŒŸ


โญ SEE ALSO โญ

๐Ÿ‘‘ AUTHOR ๐Ÿ‘‘

John Elliott <seasip.webmaster@gmail.com>.


k that's the whole page bestie, go forth and read some font binaries ๐Ÿฆ‹

Version 1.1.3 โ€” 22 January, 2021 ๐Ÿ’– mwah, that's the whole vibe, thanks for coming to my ted talk โœจ๐ŸŽ€๐Ÿซถ

๐Ÿ“ฆ where this page comes from