BDF Parser (TypeScript / JavaScript library)
Introduction
This is a BDF (Glyph Bitmap Distribution; Wikipedia; Spec) format bitmap font file parser library in TypeScript (JavaScript). It has Font, Glyph and Bitmap classes providing more than 30 chainable API methods of parsing BDF fonts, getting their meta information, rendering text in any writing direction, adding special effects and manipulating bitmap images. 0 dependencies and tested in Node.js, browsers (so you can use HTML Canvas) and Deno, it has detailed documentation / tutorials / API reference.
You can even try the Live Demo & Code Editor!
BDF Parser TypeScript (JavaScript) library (documentation; GitHub page; npm page; npm i bdfparser) is a port of BDF Parser Python library (documentation; GitHub page; PyPI page; pip install bdfparser). Both are written by Tom Chen and under the MIT License.
Installation
npm install bdfparser readlineiter
readlineiter is used for Node.js to read local file. You can instead use fetchline for browsers/Deno to fetch remote file. See Fetch Line JavaScript packages.
Quick examples
const { $Font } = require('bdfparser')
const getline = require('readlineiter') // or `require('fetchline')` for browsers
;(async () => {
const font = await $Font(getline('./test/fonts/unifont-13.0.04.bdf'))
console.log(`This font's global size is \
${font.headers.fbbx} x ${font.headers.fbby} (pixel), \
it contains ${font.length} glyphs.`)
})()
// This font's global size is 16 x 16 (pixel), it contains 57086 glyphs. import { $Font } from 'bdfparser'
import getline from 'readlineiter'
;(async () => {
try {
const font = await $Font(getline('./test/fonts/unifont-13.0.04.bdf'))
if (!font || !font.headers) {
throw new Error('Unable to load font')
}
console.log(`This font's global size is \
${font.headers.fbbx} x ${font.headers.fbby} (pixel), \
it contains ${font.length} glyphs.`)
} catch (error) {
throw error
}
})()
// This font's global size is 16 x 16 (pixel), it contains 57086 glyphs. Python code is included here only for comparison. See Python library’s documentation for details
from bdfparser import Font
font = Font('tests/fonts/unifont-13.0.04.bdf')
print(f"This font's global size is "
f"{font.headers['fbbx']} x {font.headers['fbby']} (pixel), "
f"it contains {len(font)} glyphs.")
# This font's global size is 16 x 16 (pixel), it contains 57086 glyphs. Print cropped and combined “a” and “c” with shadow effect:
const a = font.glyph('a')
const c = font.glyph('c')
const ac = a
.draw()
.crop(6, 8, 1, 2)
.concat(c.draw().crop(6, 8, 1, 2))
.shadow()
console.log(ac.toString())
// .####..####..
// #.&&&##.&&&#.
// .&...##&....&
// .######&.....
// #.&&&##&.....
// #&...##&.....
// #&..###&...#.
// .###.#&####.&
// ..&&&.&.&&&&. const a = font.glyph('a')
const c = font.glyph('c')
if (a && c) {
const ac = a
.draw()
.crop(6, 8, 1, 2)
.concat(c.draw().crop(6, 8, 1, 2))
.shadow()
console.log(ac.toString())
}
// .####..####..
// #.&&&##.&&&#.
// .&...##&....&
// .######&.....
// #.&&&##&.....
// #&...##&.....
// #&..###&...#.
// .###.#&####.&
// ..&&&.&.&&&&. ac = font.glyph("a").draw().crop(6, 8, 1, 2).concat(
font.glyph("c").draw().crop(6, 8, 1, 2)
).shadow()
print(ac)
# .####..####..
# #.&&&##.&&&#.
# .&...##&....&
# .######&.....
# #.&&&##&.....
# #&...##&.....
# #&..###&...#.
# .###.#&####.&
# ..&&&.&.&&&&. Get an enlarged version (8 times both width and height) of this “ac”, and render it in HTML <canvas> in browser with JavaScript / TypeScript (or with PIL (Pillow) library in Python):
const ac_8x8 = ac.enlarge(8, 8)
const ctx = canvas.getContext('2d')
ac_8x8.draw2canvas(ctx) const ac_8x8 = ac.enlarge(8, 8)
const ctx = canvas.getContext('2d')
ac_8x8.draw2canvas(ctx) ac_8x8 = ac * 8
from PIL import Image
im_ac = Image.frombytes('RGBA',
(ac_8x8.width(), ac_8x8.height()),
ac_8x8.tobytes('RGBA'))
im_ac.save("ac.png", "PNG") Get text “Hello!”, from right to left, with glowing effect:
const hello = font.draw('Hello!', {direction: 'rl'}).glow()
hello.draw2canvas(canvas.getContext('2d')) const hello = font.draw('Hello!', {direction: 'rl'}).glow()
hello.draw2canvas(canvas.getContext('2d')) hello = font.draw('Hello!', direction='rl').glow() Save all glyphs in Unifont as a black-and-white-two-color-only “font_preview.png” (with default width 512px):
const font_preview = font.drawall()
font_preview.draw2canvas(canvas.getContext('2d')) const font_preview = font.drawall()
font_preview.draw2canvas(canvas.getContext('2d')) font_preview = font.drawall()
im_ac = Image.frombytes(
'1',
(font_preview.width(), font_preview.height()),
font_preview.tobytes('1'),
)
im_ac.save('font_preview.png', 'PNG') Now try it your self. Copy and paste this into the Live Demo & Code Editor:
<BDF func={
(font) => {
return font.draw('Hello World!', {linelimit: 100, direction: 'tblr'})
.enlarge(3, 3).shadow(2, -2)
}
}/>
Or even this:
<BDF size={1} func={(font) => font.drawall()}/>
Deno usage
If you are using Deno instead of Node.js, you don’t need to install the package with npm/yarn, and you should replace const { $Font } = require('bdfparser'); const getline = require('readlineiter') by:
import { $Font } from "https://raw.githubusercontent.com/fontpixel/bdfparser-js/main/deno/mod.ts"
import readlineiter from 'https://raw.githubusercontent.com/tomchen/fetchline/main/packages/readlineiter-deno/mod.ts'
Copyright & links
Written by Tom Chen, under the MIT License, a permissive open-source license.
This TypeScript / JavaScript library supports Node.js, Deno and modern browsers. It has TypeScript source code, as well as compiled versions in CommonJS, ES module, minified UMD and seperate type definition files.
The documentation belongs to font.tomchen.org, a website where I put font & typography related stuff. The documentation website’s GitHub repo
