- 1 Introduction
- 2 SVG OpenType Fonts
- 3 Prototype Implementation
- 4 Adobe's Proposal
This is an old page. More up-to-date work-in-progress documentation on SVG-in-OpenType can be found at http://dev.w3.org/SVG/modules/fonts/SVG-OpenType.html or, even more recently, here http://lists.w3.org/Archives/Public/public-svgopentype/2013Jul/0003.html
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
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.
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
Robert O'Callahan's proposed alternative to SVG fonts is to embed SVG glyph data in OpenType fonts, and draw glyphs by rendering that SVG. Use the OpenType data for everything other than glyph drawing (metrics, shaping, etc).
The current status of this proposal is that it has worked its way through the W3C process and is now a proposal that has been put forward by the W3C for consideration by the MPEG group (which owns the Open Font Format (aka OpenType) spec within ISO).
The current tools for creating SVG-in-OT fonts are basic, and possibly out of date.
- Robert O'Callahan's tools
- Edwin Flores's tools
- Read Roberts's tools
- TransType (conversion only)
- FontTools Can be used to convert an OpenType font to XML so that you can insert/view/edit SVG tables (in an XML/text editor) and then recompile the font back into otf or ttf.
This work is going on in bug 719286.
The SVG table
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:
||The version of the SVG table—currently 1|
||The number of index entries (see below) in this table|
This is followed by
numIndices index entries: each entry specifies a range of glyph IDs and location of the SVG document in the table for those glyph IDs. The index must not contain any intersecting glyph ID ranges and entries must be sorted in ascending order by glyph IDs. Index entries may share
(documentOffset, documentLength) pairs, but may not have intersecting non-equal document locations.
||The first glyph ID mapped by this entry|
||The last glyph ID mapped by this entry|
||The offset from the beginning of the SVG table where the SVG document can be found containing glyphs for this range|
||The length of the SVG document for this glyph 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.
With this design, authors can easily create small fonts by putting all glyphs in a single document. They can also create efficient large fonts by putting each glyph in its own document. A UA could avoid managing too many SVG documents when rendering many glyphs, by rendering glyphs to a cache of glyph bitmaps and discarding their SVG documents as needed.
Structure of the SVG Document
Two additional attributes are supported in this SVG document:
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.
The glyphs themselves have an em-height of 1000 units with the baseline at y=0. (Note that the SVG 'viewbox' attribute can be used to easily select a different coordinate system.) The ink bounding boxes specified in the OpenType metrics tables are ignored; the ink bounding-box of each SVG glyph DOM subtree is used instead.
Two new paint server values are defined for use in SVG glyphs:
objectStroke (currently prefixed as
-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.
Two new values for
stroke-opacity are defined:
objectStrokeOpacity, which evaluate to the fill and stroke opacity applied to the text in the document that uses this font. Either value can be used with either property. Also, if
objectFill is a fully transparent color,
objectFillOpacity evalutes to zero, and likewise for
objectStrokeOpacity. (This allows authors to easily set the fill colors of glyph parts while still not rendering anything in those parts when the text is not being filled.)
A new value
objectValue is defined for the
stroke-dashoffset properties. This value evaluates to the value from the text in the document using this font, appropriately adjusted for the scale in the coordinate systems from the text document to the glyph document.
Question: is it worth supporting 'custom stroking' of SVG glyphs, or should we just make stroking stroke the path defined by OpenType, and remove all the special stroking-related properties above? It might be quite hard for authors to effectively use custom stroking.
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, scripting is disabled in the glyphs document.
Animation is enabled. (But not yet supported in Gecko.)
<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︁" /> <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
︁; 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 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. Note that it's easy to create a glyph DOM subtree containing separate "static" and "animated" glyphs such that if SMIL is enabled, the animated glyph is drawn, otherwise the static glyph is drawn.