Fork me on GitHub

Fontgenerator.js - dynamic font generation using JavaScript

Inspect the fontgenerator.js script.

This page generates a div that should contain the input-indicated character five times, masked (=made to look invisible) using a dynamically generated bespoke font that encodes that character as a zero-width glyph. You can verify that the text is actually there by copying the entire line in the purplish box, and pasting it in the base64 textarea below.

How does it work?

Following the OpenType specification, and earlier work on generating minimal TTF fonts, fontgenerator.js generates the bytecode for a minimal TTF with a character-to-glyph mapping for a single character (at the moment restricted to characters with codes between 0x0000 and 0xFFFF, due to the font sanitiser in Chrome and Firefox only supporting CMAP subtable format 4, which does not allow characters with higher code points). Since the bytecode for the minimal TTF is essentially static code, independent of the character(s) the font models, everything but eight bytes in the byte code are actually boilerplate code. This means we can generate these minimal fonts for any character we like, by simply changing one value, encoded as a four byte value in only two places.

Fontgenerator.js simple generates the boilerplate code, with your character's byte code set in the right places, and then turns that byte code into ASCII string data using the JavaScript btoa() function, which takes binary code, and converts it to BASE64-encoded ASCII text. This can then be used in a data-URI so that we can load the font as if it were a real file using a CSS @font-face rule.

So when you hit "generate", the script actually generates a proper TTF font in memory, converts its bytecode to a string, tells the browser to interpret the string as a font resource, and then styles a text consisting solely of the character you generated the font for. Because the font uses a zero-width glyph for the character, this effectively makes the text zero pixels wide, and for all intents and purposes invisible, while still being "real" text. Change the font to a normal, visible font and it shows up like any other piece of text on the page.

Why is this useful?

This little bit of code was written to solve a problem that people were having in the PDF.js project, where a PDF file may have fonts embedded for rendering text with, but no way to tell whether an extracted font has actually finished loading. Drawing the text onto the canvas when the font isn't ready yet will not result in an error message, but instead draws the text with the wrong font. Clearly, something that is undesirable when rendering PDF files. Using the fonts that fontgenerator.js can generate, it is possible to style a piece of sample text with "pdffont, bespokefont" and see whether the PDF font is done loading by interval-checking how wide the text is. If it is zero width, the font is not done loading yet. If it's not zero-width, the PDF's own font is available and the real text can be rendered onto the canvas. The reason fontgenerator.js lets you specify the character for the sample text is that not every font is guaranteed to have the letter you hardcode, especially since PDF allows subset fonts. If your text never uses the letter 'f', it simply won't save that letter in the PDF's copy of the font. As such, you want to extract the font, find a letter it does implement, and then verify loading has finished based on that letter, thus making sure every font can be checked for, even if you don't know which letters it will contain before opening the PDF.