Friday 1 February 2013
OpenType is the industry standard font format. This is good. However, OpenType fonts severely limit what can be drawn in a glyph: basically, you can fill simple paths, and that's it. Some use-cases, e.g. fonts for emoji, require colored and even animated glyphs. SVG is the vector graphics format for the Web platform, so it makes sense to support SVG content in glyphs. The SVG Fonts spec defines a non-Opentype SVG-based font format which in theory lets glyphs contain any SVG content. However, this format has some deficiencies that I believe make it unsuitable for the Web:
- SVG Fonts have very weak shaping support, which makes them unusable with Indic and other languages. A solution which is unusable by a large fraction of the world's population is inadequate for the Web.
- As a side effect, SVG Fonts do not support advanced typographic features that are offered by OpenType and are being exposed to Web authors via the CSS3 Fonts spec (e.g. stylistic alternates).
- SVG Fonts have a somewhat broken model for how style on the text affects rendering of the glyphs: CSS style inherits directly from the text to the glyphs. This is difficult to implement in a performant way, and doesn't do what authors expect.
The Web needs an approach that overcomes these problems.
Introducing SVG Glyphs In OpenType!
We propose to extend OpenType with support for glyphs consisting of SVG content. A new "SVG" OpenType table is defined, containing one or more SVG documents, each of which contains one or more glyphs. It's almost as simple as that! SVG glyph documents are subject to the same restrictions as SVG image documents, i.e. animation is supported but not scripting or external resource loads. CSS style is not inherited from the text to the glyphs; instead, the stroke and fill property values of the text are available in the glyphs document as new CSS values "context-fill", "context-stroke" etc. (These new values would also be useful with other SVG features such as markers.)
This proposal has been implemented in Firefox. It's disabled by default (in order to not pollute the Web with our not-yet-standardized implementation), but can be enabled by toggling gfx.font_rendering.opentype_svg.enabled in about:config (test page here). The only significant missing feature in our implementation is that animation is not yet supported. There are some bugs :-). Currently "context-fill" etc are named "-moz-objectFill" etc.
This approach has some nice advantages:
- Very simple spec and implementation. This proposal only affects glyph rendering. Shaping relies entirely on existing OpenType features, so there is nothing to say about that in the spec, and nothing new to implement. An intern was able to design and implement most of this feature in a few months with no prior Gecko experience. (Thanks Edwin!)
- No way to mutate the glyph DOM, which simplifies implementation considerably.
- Full power of OpenType shaping available, including support for every script supported by OpenType, which is to say almost all of them. In theory this should also "just work" in fonts that use Graphite, an alternate, more extensible shaping engine for OpenType.
- Powerful ability to customize the stroking and filling of glyphs based on stroke and fill properties of the text.
- Fallback to regular OpenType glyph rendering for renderers that don't support SVG glyphs, and also if we need to obtain the outline of a glyph as a path (e.g. for <canvas> addText()).
Thanks to Edwin Flores for doing the implementation work and Cameron McCormack for helping design the feature and write up the spec.