processing.js, canvas, custom fonts and @font-face. Chapter 3

So I’ve been spending the last while learning about fonts on the web. The font types, restrictions, tricks.

One thing in particular is displaying custom fonts in the browser, without having to download the font; we can do this using the @font-face css rule, which I have discussed in chapter one of this font adventure.

The problem being that the font isn’t actually loaded by the css rule, but at the first use of the new font. This is not a huge deal in most normal, static webpages displaying a bit of unstyled text while it downloads the custom font, then updating the font, coined in this extremely helpful post, as FOUT(flash of unstyled text). Something dynamic, like canvas, is a bit more of an issue.

When canvas first tries to display the text, it is displayed for good, until it is drawn over, and displayed again, so there is no real time update of the new text once it is downloaded. This is not a problem if we write the text in a constant draw loop, which is probably the best way to do it anyway. However, that is not perfect, and we need a way to preload the text, so it is ready for the whole of the canvas. Fonts are not scannable by the browser, as it is an obvious security flaw. The first thing we need to do, is declare in our code that we want to preload a font. Luckily processing.js, the library I am making this for has a preloading directive (mentioned here) already created, I just have to plug into it. Now that I know what font I will be using, I have to create a hidden dom element and use this font, to start the loading, but I also have to stall the canvas code, to only begin after all my fonts are finished downloading, without checking which fonts are installed. I can do this with a pretty messy hack, which consists of creating two elements (one of which we just created) and writing some text to it, then compare the size of the text, in pixels, to each other. If they are the same, the custom font is still using the defaulted font, which means my custom font is not yet downloaded. I got this all working today, and I threw up a small demo of it here.

A few interesting things to note about the demo, is that I can load a font from a data uri, and not a filepath, but it was slow using it, because the data uri string, which was really long, was the only unique identifyer I had, so if I wanted to access it, I had to pass in this long string. I fixed this by allowing the font @pjs directive accept a valid JSON object, so I can define a fontName, and a url, and access the font by name, and not by url. Example(including the data uri):

/* @pjs font='{"fontFace": "ADamnMess", "url": "data:font/opentype..."}', 'yanone.ttf'; */

Then use it by name, if a JSON object is not provided, a string with a url is also acceptable, but must be referenced inside the processing code by the url as well.

And, to put it all together in a processing sketch, looks like this (link includes the data uri which is the top most super long line):

/* @pjs font='{"fontFace": "ADamnMess", "url": "data:font/opentype"}',
 'yanone.ttf'; */

PFont myFont;

void setup() {
 background(0);
 size(200, 200);

 myFont = createFont("ADamnMess", 32);
 textFont(myFont);
 text("hello", 52, 60);

 myFont = loadFont("yanone.ttf");
 textFont(myFont, 32);
 text("world!", 50, 100);
}

Advertisements

One Response to “processing.js, canvas, custom fonts and @font-face. Chapter 3”

  1. Hi Scott,
    I’m not sure if you’ve seen it already, but Google recently introduced some web font APIs and libraries (I’m using it to load the Reenie Beanie font on http://sketchpad.cc ). Their documentation includes notes on some of the issues you describe in your recent posts (browser compatibility, pre-loading vs flash, etc). If you haven’t taken a look yet, you may find something useful in their docs. Look forward to trying this out soon!
    -Ari

    starting point:
    http://code.google.com/apis/webfonts/docs/getting_started.html

    avoiding the flash:
    http://code.google.com/apis/webfonts/docs/webfont_loader.html

    cross-browser compatibility:
    http://code.google.com/apis/webfonts/faq.html

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: