SVGOpenTypeFonts

Introduction

Use Cases

SVG Fonts address some use-cases which cannot be addressed using current OpenType-based solutions. For example:

  • Editable text where the glyphs display a "shiver" effect
  • Draw freehand graphics with self-intersecting curves and use them as glyphs for a font
  • Japanese "emoji" with colored glyphs

Limitations Of SVG 1.1 Fonts

Internationalization

SVG Fonts have very weak shaping support, which makes them unusable with Indic and other languages. Therefore we need a solution to address the above use-cases that also handles complex shaping. OpenType already supports shaping for most of the world's languages and because of the large ongoing investment in OpenType fonts and processing engines, will broaden its support over time. So, can we leverage OpenType to handle the above use-cases?

Advanced Font Features

SVG Fonts lack support for features such as stylistic alternates.

Style Inheritance

The way SVG font glyphs inherit style from the text is both broken for authors and difficult to implement.

An example of how it's broken for authors: if the author specifies 'stroke-width:2' on a piece of text where some characters are rendered with system font F and other characters are rendered with SVG font S, and the glyphs of S contain simple path shapes, then the glyphs of F get a stroke width of 2 user-space units, but the glyphs of S get a stroke width of 2 glyph-space units, which will typically be invisible.

It's difficult to implement because Gecko (and Webkit, and probably other engines) keep persistent computed style data attached to DOM nodes, so having the style inherit differently depending on how the nodes are being used is inefficient and intrusive.

SVG OpenType Fonts

Idea: embed SVG glyph data in OpenType fonts, and draw glyphs by rendering that SVG. Use OpenType data for everything else (measurement, shaping, etc).

Prototype Implementation

This work is going on in bug 719286.

The SVG table

Not yet implemented -- still currently using old format where 'SVG ' table contains one SVG document for the whole font.

We define a new optional OpenType table 'SVG '. This table contains one or more UTF-8 encoded SVG documents defining SVG glyphs.

The table begins with a header:

Name Type Description
numDocuments USHORT The number of SVG documents contained in this table
numIndices USHORT The number of index entries (see below) in this table

This is followed by numDocuments document headers describing the location and length of the SVG documents:

Name Type Description
offset ULONG The offset of the document into the SVG table
length ULONG The length of the document

Then numIndices index entries: these specify which documents should be searched for which ranges of glyph IDs.

Name Type Description
startGlyphId USHORT The first glyph ID mapped by this entry
endGlyphId USHORT The last glyph ID mapped by this entry
documentId USHORT The (zero-indexed) document index which should be searched for glyphs in this range

Finally, the SVG documents themselves which are to be UTF-8 encoded, and whose length and offset are described by the document list above.

If the index contains overlapping glyph ID ranges, the earlier entry wins.

Structure of the SVG Document

Two additional attributes are supported in this SVG document: glyphid and glyphchar, which may be used on any SVG graphic element or container element.

glyphid is a number specifying a glyph ID. That glyph ID is rendered using that element.

glyphchar is a string of one character optionally followed by a Unicode Variation Selector. The glyph ID to associate with the glyph is then resolved using the cmap table. That glyph ID is rendered using that element.

If a glyph ID could be rendered by more than one element, then the first element in the document for that glyph ID wins.

SVG Glyphs

The glyphs themselves have an em-height of 1000 units (although maybe worth changing to 2048 to match TrueType convention) with the baseline at y=0. The width:height ratio of the glyph is to be the same as in the TrueType font—the glyph is simply clipped to the TrueType bounding box.

Two new paint server values are defined for use in SVG glyphs: objectFill and objectStroke (currently prefixed as -moz-objectFill and -moz-objectStroke). These values specify the fill or stroke applied to the text in the document that uses this font. Unlike SVG 1.1's style inheritance approach, they automatically take account of the change in coordinate systems from the document containing the text to the glyph document. We also plan to add additional values objectFillOpacity, objectStrokeOpacity, and objectValue (for stroke-width, stroke-dash-array, etc).

Security

For security's sake the SVG document is not allowed to refer to external resources—it may, however, contain resources in the form of data URIs. Moreover, scripts in the SVG document will not be run.

Animation will be allowed.

Example

<svg xmlns="http://www.w3.org/2000/svg">
  <rect x="100" y="-900" width="800" height="800" fill="objectFill" stroke="objectStroke" glyphchar="M" />
  <circle cx="500" cy="-500" r="300" fill="red" stroke="objectStroke" glyphchar="M&#xfe01;" />
  <path class="SamplePath" d="M100,200 C100,100 250,100 250,200 S400,300 400,200 Z" fill="objectFill"
    stroke="black" glyphid="45" />
</svg>

In this example we have three glyphs defined: a rectangle-shaped glyph to render M as; a circle-shaped glyph for M with the Unicode Variation Selector &#xfe01;; and a path to replace some glyph ID, usually a glyph ID which would be the result of substitution—for example via the GSUB table.

Also worth noting are the negative y coordinates due to SVG's y-down coordinate system and our placing the baseline at y=0.

Adobe's Proposal

Adobe are keen on a similar idea, an early proposal of which can be found here.

The main differences I can see are that each glyph definition has a whole SVG document. Also, they have two glyph definitions per actual glyph -- one static, one animated. I don't think this is necessary, though; we can let static glyphs be the glyph without any animations applied.