Custom fonts with dojox.gfx

By on September 8, 2008 12:01 am

Recently, there’s been a spat of editorials regarding custom fonts for the web—with two competing proposals (Microsoft’s EOT and embedding a TrueType font directly with the @font-face directive), as well as the well known Fahrner Image Replacement technique, and the related sIFR (Scalable Inman Flash Replacement) technique.

I’m pleased to announce yet another technique: rendering SVG font definitions using dojox.gfx, coming in the Dojo Toolkit 1.2 release!

Fake newspaper demo

The problem

Custom fonts for the Open Web have been a pain-point since almost the beginning of the Web. Plagued by a number of issues, typography for the Web has been limited to working with a subset of fonts that can be reasonably expected to be installed on everyone’s computer. The reasons for this stagnation include the following:

Font licensing issues

One of the main reasons custom fonts have not found a good home on the Web has to do with licensing issues—simply linking to a True Type font (a la the @font-face directive) enables font piracy in the worst way. Jeffrey Zeldman said it best, in this comment (scroll down to the third comment, unfortunately there are no direct links available):

The problem with @font-face is that it violates the font manufacturing license agreement with the end-user. Put simply, it readily enables font piracy. Any font embedded this way can be downloaded to the web viewer’s machine, and used as if he or she had paid for the font. Hacker skills are not required. The ability to download embedded fonts is readily discoverable to any competent browser user.

Fonts are closely and jealously guarded by most creators; simply put, it takes an incredible amount of effort to create one well. Because of this, most font manufacturers limit licenses to a single computer. To make it worse, most fonts cannot be copyrighted—this is because almost all fonts can be considered derivate works (i.e. most have a beginning from somewhere in the days before digital typesetting).

To try to satisfy both the licensing issues that come with most fonts, and to prevent font piracy, a few proposals have been made.

Embedded Open Type (EOT)

The most promising (in terms of satisfying both font manufacturers and web users) is Microsoft’s Embedded Open Type proposal. The basic concept is for a legitimate font license holder to convert their font to the EOT format (using Microsoft’s tools), binding the font to the web site serving it. Recently, Microsoft has teamed up with the Ascender Corporation (a major font manufacturer) to try to bring the EOT specification to the W3C, as well as providing online tools for converting a font to the EOT format.

The problem with the EOT concept though is that only Internet Explorer supports it; none of the other browser manufacturers have been willing to implement it.

Font Linking

Another approach is direct font linking, recently added, and then removed (as far as I can discern), in Apple’s Safari 3.1 browser. The problem with this approach is that it violates most font license agreements; the aforementioned Font Embedding site has a pretty good explanation of why it violates most agreements.

Image replacement techniques

The most common technique used today for custom typography is to create an image with the desired typography, and use CSS techniques to replace text with them. Both static and dynamic techniques can be used; sIFR is probably the best known, and a number of other sites will implement something like a PHP/GD stack, where the server is called with the text and parameters required, and the server generates the image on-the-fly and sends it back out to the client.

Revisiting font licenses

Two other efforts have been quietly underway to create Open Source-based licensing schemes for fonts. The first is the SIL Open Font License, designed to allow for modification and redistribution; the other is releasing a font under the GNU with font exception license. While the OFL seems like a genuine effort, some restrictions still make it difficult to use for the Web; the GNU with font exception is the license of choice for fonts included with Linux. (Also, an honorable mention goes out to the Creative Commons for their efforts with this thorny issue.)

A solution

In general, the issues surrounding font usage have to do with the ability for someone to visit a web site, grab a specific file, and be able to reuse it without paying for a legitimate copy within any of the most commonly used programs (such as Office). Because of this concern, both the EOT and sIFR techniques work–because the fonts are embedded in a form that is not reusable in a common way.

One approach: the SVG Font Specification

Similarly, the SVG Font specification allows for the same concept—by working with a specific font definition, especially one that can be customized for the specific usage, the spec avoids most of the prickly issues surrounding licensing.

SVG fonts are relatively simple in concept; within the <defs> element, you define the main specifications of a font, and then you include specific glyph definitions. Optionally, you can include character-specific kerning information (the space between letters); some fonts include this type of hinting, and the SVG specification supports it.

Implementing the SVG Font specification with dojox.gfx

By taking the approach of loading an SVG font definition, parsing it and translating it to the dojox.gfx API, we were able to implement the ability to use custom font definitions within the context of native browser support. No plug-ins are needed; just generate your font, and go. Here’s an example using two “free-as-in-beer” fonts to create a page similar to one of the sIFR demonstrations (screenshot below):


Fake newspaper demo

To create the page, we use two fonts (a serif font based on Bookplate, and another based on a Eurostyle font), and dynamically swap out certain elements onload (a la sIFR). In addition, there are two other demonstrations—an example of customized pie charts, and a playful comic, showing how the font replacement works on the fly:

Comic demo

(Yes, that’s my mug shot; I traced it using Adobe Illustrator and converted it to dojox.gfx. You can make me say whatever you’d like =) )

Using dojox.gfx.VectorFont

Using the fonts are simple yet somewhat complex; unfortunately this is the nature of the beast. In future revisions, simpler APIs will be introduced; for now, you draw your text using the font directly.

Step 1: Create your font definition.

The first step is to create your SVG font definition. There are a number of tools out there you can use; we used the Batik ttf2svg conversion tool.

One thing that is great about using SVG Fonts is that you can remove the glyphs that you don’t need, minimizing the size of the generated SVG. This is a good thing—some converted fonts can be very large (on the order of 100+ KB) when including all glyphs, so removing them helps us minimize our font file download size.

(Note that unfortunately we cannot work with compressed SVG (i.e. svgz) files.)

Step 2: Load your font

The next step is the load up your font via the dojox.gfx API:

dojo.require("dojox.gfx");
dojo.require("dojox.gfx.VectorText");

var myfont = dojox.gfx.getVectorFont(someUri);

This will locate your SVG definition, parse it and prepare your font for usage.

Step 3: Write something!

To render something, you follow these basic steps:

  1. Create a dojox.gfx Surface to write on
  2. Create a dojox.gfx Group; you’ll use this to write into
  3. Call the font’s draw method.

Let’s take a basic example; we’ll use the font we “loaded” above, and write “The rain in Spain falls mainly on the plain.”.

var s = dojox.gfx.createSurface(someNode, width, height);
var g = s.createGroup();
var phrase = myfont.draw(
    g,
    { text: "The rain in Spain falls mainly on the plain.", align: "middle" },
    { size: "3em" },
    "blue"
);

The font’s draw method (the main method) takes 4 arguments:

  1. the dojox.gfx.Group to render into
  2. a “Text Arguments” object; this is a keyword/configuration object that specifies a number of parameters about the text
  3. a “Font Arguments” object; like the Text Args, this is a keyword/configuration object that specifies font arguments
  4. A fill color

It returns a dojox.gfx.Group; this group is a direct child of the group you passed to the function.

The structure that is generated by the font is pretty complex; there are a lot of groupings and translation transformations. Because of this, we require the original group so that you can perform your own transformations without affecting any of the internal ones created for the phrase. The pie chart example (from above) demonstrates this; all font renderings are rotated based on the position within the chart. In fact, this is one of the greatest strengths of the VectorFont—the ability to create the entire block as any other basic shape in dojox.gfx.

Other features

In addition to straight font rendering using a specific size (e.g. 12px, 3em, “medium”), you can also draw using two other modes: a flow mode, and a fitting mode.

Drawing in flow mode

To draw something in flow mode, you specify two additional named parameters in the Text Arguments object:

    { 
        text: "The rain in Spain falls mainly on the plain.", 
        align: "middle", 
        width: 200, 
        fitting: dojox.gfx.vectorFontFitting.FLOW 
    }

By specifying the width and the FLOW constant, you are asking the draw() method to break your text up, based on the size specified in the Font Args object, into as many lines needed to render the text. This is similar to the way HTML blocks are rendered; one difference is that there’s no overflow, so you need to be careful to ensure your surface is tall enough to accommodate all of your text.

Drawing in fit mode

The fit mode allows you to specify a bounding box for your text. The font will attempt to “best fit” your phrase within that box by finding the largest font size/scale that will fit within this bounding box, breaking your text up into lines as needed; in the process, the draw method will ignore any size parameters you’ve passed.

To use the fit mode, pass a width, height and the FIT constant to your Text Arguments object:

    { 
        text: "The rain in Spain falls mainly on the plain.", 
        align: "middle", 
        width: 200, 
        height: 150, 
        fitting: dojox.gfx.vectorFontFitting.FIT 
    }

Caveats

As with most things, VectorText comes with a few caveats.

The elephant in the room: Internet Explorer.

Because of the poor performance with VML—including VML’s lack of both a cubic bezier curve and arcs—rendering fonts (especially complex ones) in Internet Explorer can give you less-than-stellar results. Using the Silverlight plug-in as a renderer will help somewhat, but since it is not so ubiquitous you cannot yet rely on it for all users of Internet Explorer.

Rendering too much text.

Since each glyph (i.e. character) is created as a dojox.gfx.Path object, large amounts of text can slow a browser down to a point where it is unusable. Because of this, we recommend that you treat this the same way you’d treat sIFR—use it sparingly, and don’t use it to render all of the text on your pages.

Text on a path

Text on a path is not supported at this time.

a11y /i18ln

Because of the nature of the renderers, in general no text drawn by a GFX font will be considered a11y-friendly. We’re working on changing this but we don’t know when we’ll have a solution.

Internationalization can be supported—but to do so will require that your SVG font definition supports the glyphs needed to render text. Vertical and right-to-left text is not currently supported but is planned for future releases.

In conclusion

With the new VectorText capabilities, dojox.gfx takes vector drawing to a whole new level for the Open Web. Happy drawing!

Comments

  • Very impressive project. I like that you can use only some glyphs from a font, which is what I was used to doing in years of Flash work; which is quite necessary – as I recall, the internationized Arial font is 35 megs (as an example).

    If this catches on, having a library of fonts in a CDN, potentially cached on a user’s computer would be quite valuable – and quite realistic for project based apps with a captive audience, like on an intranet.

    I’m curious as to the feasibility of compressing the SVG font definition and uncompressing it with JavaScript, maybe offloading that chore into something like Gears.

  • Nifty!

    BTW, you should be able to configure your web server to serve SVG files with gzip compression (to avoid having dojo do the decoding): http://wiki.svg.org/Server_Configuration:Apache

  • Pingback: Understanding Design & Computers: DojoToolkit Smashes EOT Web Fonts With SVG!()

  • This is simply fanstastic. Thank you guys!

  • Pingback: Ajaxian » Custom fonts thanks to rendering SVG font definitions()

  • ttrenka

    @Cameron:
    Yes, you should–but this is a server-based solution and not a client-side one, and therefore I didn’t mention it.

    What I was referring to was using .svgz files as opposed to .svg; we don’t have the ability (though we might one day) to deal with the decompression built into the SVG specification, since we are loading and parsing the SVG file manually using the DomParser in dojox.xml (which I wrote a while ago for this exact reason–loading and interpreting SVG in a non-browser-specific way).

  • Dave Crossland

    Sadly, with Firefox, when I go to “File, Save As” and save the “Dojo Times” demo.html page to my hard disk, then go to the File menu and check “Work offline,” and then load the saved page, the special-font text disappears – it doesn’t render with the font, and it also doesn’t fall back to the generic font. EOT also suffers from this, so for this to eclipse EOT – which I think is quite possible! :-) – this aspect will need to be improved. It would also be great if the text was somehow still selectable, so that when text is copy and pasted from browser canvas to browser textinput box (or email program or word processor or whatever) the full text is copied faithfully.

  • i18ln

    “Internationalization can be supported—but to do so will require that your SVG font definition supports the glyphs needed to render text. Vertical and right-to-left text is not currently supported but is planned for future releases.”

    Looks interesting, but what about complex scripts (Bengali, Devanagri, Khmer, Sinhala, Tamil, Tibetan, etc) which require a lot of contextual glyph replacing and positioning?

    Will “smart font” lookups such as those in OpenType, ATSUI and Graphite fonts for complex non-Roman scripts work?

    – Chris

  • Wow, interesting approach with some great potential IMHO.

    A few suggestions:
    – investigating Fontforge’s SVG font creation/tweaking abilities
    (scriptable via python and under BSD-like licensing)
    – exposing the path of the font source
    – exposing the font licensing/authorship metadata somewhere in the
    framework (the NAME table of TrueType: copyright, license, license_url,
    designer, designer_url, manufacturer, description) would be extremely useful
    – making the text selectable

    For i18n, I suggest looking at earlier research done by Chris Lilley from W3C: extending SVG with the Graphite smart font technology:
    http://www.unicode.org/iuc/iuc24/a339.html

    Even if you change the format, obviously the licensing chosen by the upstream designer stays and needs to be respected.

    I’d recommend using open fonts in your demo: Wide choice on
    http://unifont.org/fontguide and http://scripts.sil.org/OFL_fonts
    (should make the point better than restricted fonts!).

    As for you licensing assessment, I think many would be interested to
    hear what makes you think that GPL + font exception is better suited than the OFL in this scenario (BTW, which version of the GPL? And the exception is currently undergoing a rewrite as there are issues). Most recent
    font releases have been under OFL as is it a recommended license for fonts in
    the FLOSS world
    . What restrictions do you have in mind? Also AFAIK
    CC-licensed fonts are not very common. CC itself doesn’t want to be
    involved in font licensing.

    BTW, you may consider bundling some open fonts with your framework directly.
    Looking forward to even more Dojo goodness in the future :-)

  • ttrenka

    @yosch:
    WRT to the font licensing, I went back and forth with a very large, unnamed entity who has a very vested interest in the licensing aspect of things, and they were the ones that chose GPL + font exception over the OFL. I was originally going to include a copy of Gentium but the language of the license leaves a bit to be desired. Since I’m not a legal expert, all I can say is that I went with the best advice we could get, and this is why we include Gillius (GPL + Font exception) in the toolkit itself.

    AFAIK, the SVG font specification does not support meta information such as designer, etc. If it did, I’d include it.

    WRT to text being selectable, I made deliberate mention that we’re not supporting a11y right now (this is one of the main reqs for a11y). The issue is that I am drawing each glyph directly; there’s no way for me to designate to a browser that something should be treated as text and not as a drawing. And it sucks but that’s the reality at this point. Perhaps a hack will be forthcoming but I’m not hopeful at the moment.

    The path of the font source is key and is included with every glyph defined in the font (take a look, d attribute).

    I looked at FontForge and a number of other generator sources, and frankly Batik was the easiest to use. But I made sure (I hope, bug reports welcome) that anything generating font definitions according to the SVG spec would work–so if you prefer FontForge, that should be fine too.

    @Chris Flynn: I did not implement vkern, nor did I implement RTL. However, both should be pretty straightforward to do, and in the end (since this lies at the end of the font drawing chain) doing things such as Tamil should be straightforward.

    @Dave Crossland: yes, it’s unfortunate and the nature of the tech (see my notes about a11y, above–it’s all related.)

  • At some point would it be possible to just call gfx_Text.setFont, pass in a vector font and expect this to work? Without doing the drawing business ourselves?

  • ttrenka

    The API of the VectorFont was done in such a way as to make it work with a helper method, the same way that the rest of dojox.gfx works. In fact, most of the .draw() signature was designed to look exactly like the surface.createText method, so that at some point (hopefully 1.3), you’d be able to do something like:

    loadFont(url);
    myGroup.createText(textArgs, { size:”14px”, font:”MyCustomFontName” }, …);

    The only issue with that, and the reason why it was not included with the 1.2 release, is that the vector fonts return a Group and not a Text object and we want to nail this down before releasing it into the wild.

  • This is REALLY AWESOME stuff and looking forward to the createText support. I just haven’t been able to get the start/middle/end aligns to work… but worked around it by calling getWidth() and then translating.

    Also, when trying to apply a translate transform:
    var phrase = myfont.draw( … );

    //this doesn’t work
    phrase.setTransform(dojox.gfx.matrix.translate(10, 10));

    //but, this does
    phrase.children[0].setTransform(dojox.gfx.matrix.scale(scale));

  • Sorry, I meant
    phrase.children[0].setTransform(dojox.gfx.matrix.translate(10, 10));

  • ttrenka

    Couple of quick things:

    WRT to start/middle/end: this only “appears” to work when you are doing multiline text, and not when it’s a single line. The transform actually *does* happen for the single line but because it’s mostly a fitting algorithm, it’s basically useless.

    WRT to the translate, what you basically need to do is either applyRightTransform (not setTransform), or you need to do something like this:

    phrase.setTransform(new dojox.gfx.Matrix2D([
    dojox.gfx.matrix.translate(10,10),
    phrase.getTransform()
    ]));

    I haven’t found a way around it yet though the idea behind the current design is to allow you to simply translate the group you pass to the draw method, as opposed to the group you get back from it.

  • JoZ

    Not satisfied about that… You can’t even make a simple in-browser text search! Not to mention SEO issues and being semantically standard complaiant…

  • Pingback: Dojo: The Definitive Guide » Blog Archive » Dojo, Now With Drawing Tools (Linux Journal Reprint)()

  • Is there a way to apply filters to dojo.gfx embedded fonts? For example, could a gaussian blur be applied to a font to create a soft drop shadow?

  • ttrenka

    The fonts are all rendered as groups and paths, so if the underlying renderer supports filters, then yes, they can be applied.

    I don’t think we really support filters with dojox.gfx, though; at least I don’t remember seeing them, because of the whole VML thing. Probably should be something we look into.

  • Hello, I just tried to render and place some text with dojox.gfx, and I have to say….. Thanks! This is one amazing piece of work. Especially the getWidth() is working perfectly, which is not always the case in other context or libraries that I tried in the past. Great job.

  • Pingback: lrbabe » Blog Archive » The state of cross-browser vector graphics()