SVGOpenTypeFonts: Difference between revisions

From MozillaWiki
Jump to navigation Jump to search
(Add FontTools to the list of tools)
 
(37 intermediate revisions by 3 users not shown)
Line 1: Line 1:
= Introduction =
= Introduction =
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


== Use Cases ==
== Use Cases ==


SVG Fonts address some kinds of use-cases which cannot be addressed using current OpenType-based solutions:
SVG Fonts address some use-cases which cannot be addressed using current OpenType-based solutions. For example:
* Glyphs of arbitary SVG content (including animation)
* Editable text where the glyphs display a "shiver" effect
** Editable text where the glyphs display a "shiver" effect
* Draw freehand graphics with self-intersecting curves and use them as glyphs for a font
** Draw freehand graphics with self-intersecting curves and use them as glyphs for a font
* Japanese "emoji" with colored glyphs
** Japanese "emoji" with colored glyphs
* Create and manipulate structured font data via script and/or text editor
** Web-based font editors


== Internationalization ==
== 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?
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 =
= SVG OpenType Fonts =


Brainstorming exercise: what if we defined an XML serialization of OpenType fonts? Like TTX except better:
[http://robert.ocallahan.org/2013/02/svg-in-opentype-new-approach-to-svg.html 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).
* Use attributes instead of elements where possible.
* Where values have sensible defaults, allow them to be omitted.
* Where values are defined in the spec as being easily computable from other font data, compute them in the user-agent. Automatically computing bounds for glyphs would help a lot.


Then we could extend the format to allow arbitary SVG content for some or all of the glyphs. We would use OpenType to shape text and apply typographical features, then use SVG just to render the glyphs.
The current status of this proposal is that it has [http://lists.w3.org/Archives/Public/public-svgopentype/2013Oct/0002.html worked its way through the W3C process] and is now a [http://www.w3.org/2013/10/SVG_in_OpenType/ proposal] that has been put forward by the W3C for consideration by the MPEG group (which owns the [http://mpeg.chiariglione.org/technologies/media-coding/font-coding Open Font Format] (aka OpenType) spec within ISO).


== Compatibility ==
== Tools ==


We should design the serialization to be compatible with a subset of SVG 1.1 Fonts wherever it's easy to do so. If we do this, the proposal can be viewed as taking a subset of SVG 1.1 Fonts, redefining it to be based on OpenType (except for the actual glyph rendering), then adding in syntax for OpenType features such as complex shaping and whatever else is needed.
The current tools for creating SVG-in-OT fonts are basic, and possibly out of date.


== API ==
* [https://github.com/rocallahan/svg-opentype-workshop Robert O'Callahan's tools]
* [https://github.com/edf825/SVG-OpenType-Utils Edwin Flores's tools]
* [http://lists.w3.org/Archives/Public/public-svgopentype/2013Dec/0003.html Read Roberts's tools]
* [http://www.fontlab.com/font-converter/transtype/ TransType] (conversion only)
* [https://github.com/behdad/fonttools/releases 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.


* Support referencing SVG Opentype Font elements from @font-face and the SVG 'font' attribute
= Prototype Implementation =
* Add an API that takes a DOM reference to a font element and returns a [http://dev.w3.org/2006/webapi/FileAPI/#dfn-Blob Blob] for a binary OpenType font (SVG glyphs will be discarded)
* Potentially we could also add an API to convert binary OpenType font data to a DOM subtree


== Implementation ==
This work is going on in {{bug|719286}}.


The simple way to do it would be to generate actual OpenType font data, excluding SVG glyph content, and pass that data to Harfbuzz for shaping. Then when drawing glyphs, call back to layout to draw glyphs that have SVG content. For bonus points, convert glyphs consisting of SVG paths into OpenType glyphs when possible, so we get subpixel rendering.
== The SVG table ==


= Style Inheritance =
We define a new optional OpenType table '<code>SVG </code>'. This table contains one or more UTF-8 encoded SVG documents defining SVG glyphs.


The way SVG font glyphs inherit style from the text is both broken for authors and difficult to implement.
The table begins with a header:
 
{| class="wikitable"
!Name
!Type
!Description
|-
|<code>version</code>
|<code>USHORT</code>
|The version of the SVG table&mdash;currently 1
|-
|<code>numIndices</code>
|<code>USHORT</code>
|The number of index entries (see below) in this table
|}
 
This is followed by <code>numIndices</code> 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 <code>(documentOffset, documentLength)</code> pairs, but may not have intersecting non-equal document locations.
 
{| class="wikitable"
!Name
!Type
!Description
|-
|<code>startGlyphId</code>
|<code>USHORT</code>
|The first glyph ID mapped by this entry
|-
|<code>endGlyphId</code>
|<code>USHORT</code>
|The last glyph ID mapped by this entry
|-
|<code>documentOffset</code>
|<code>ULONG</code>
|The offset from the beginning of the SVG table where the SVG document can be found containing glyphs for this range
|-
|<code>documentLength</code>
|<code>ULONG</code>
|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: <code>glyphid</code> and <code>glyphchar</code>, which may be used on any SVG graphic element or container element.
 
<code>glyphid</code> is a number specifying a glyph ID. That glyph ID is rendered using that element.
 
<code>glyphchar</code> 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 <code>cmap</code> 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 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: <code>objectFill</code> and <code>objectStroke</code> (currently prefixed as <code>-moz-objectFill</code> and <code>-moz-objectStroke</code>). 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 <code>fill-opacity</code> and <code>stroke-opacity</code> are defined: <code>objectFillOpacity</code> and <code>objectStrokeOpacity</code>, 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 <code>objectFill</code> is a fully transparent color, <code>objectFillOpacity</code> evalutes to zero, and likewise for <code>objectStroke</code> and <code>objectStrokeOpacity</code>. (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 <code>objectValue</code> is defined for the <code>stroke-width</code>, <code>stroke-dasharray</code>, and <code>stroke-dashoffset</code> 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.'''
 
== Security ==
 
For security's sake the SVG document is not allowed to refer to external resources&mdash;it may, however, contain resources in the form of <code>data</code> URIs. Moreover, scripting is disabled in the glyphs document.
 
Animation is enabled. (But not yet supported in Gecko.)
 
== 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&amp;#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 <code>M</code> as; a circle-shaped glyph for <code>M</code> with the Unicode Variation Selector <code>&amp;#xfe01;</code>; and a path to replace some glyph ID, usually a glyph ID which would be the result of substitution&mdash;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.


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.
= Adobe's Proposal =


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.
Adobe are keen on a similar idea, an early proposal of which can be found [http://lists.w3.org/Archives/Public/public-svgopentype/2011Oct/0000.html here].


A better design would be to specify new values for 'stroke', 'fill' and 'stroke-width' such as 'text-stroke', 'text-fill' and 'text-stroke-width' to be used in glyphs. These new values would automatically grab the stroke, fill and stroke-width from the text, rescaling them as necessary.
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.

Latest revision as of 03:58, 16 December 2014

Introduction

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

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

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).

Tools

The current tools for creating SVG-in-OT fonts are basic, and possibly out of date.

Prototype Implementation

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:

Name Type Description
version USHORT The version of the SVG table—currently 1
numIndices USHORT 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.

Name Type Description
startGlyphId USHORT The first glyph ID mapped by this entry
endGlyphId USHORT The last glyph ID mapped by this entry
documentOffset ULONG The offset from the beginning of the SVG table where the SVG document can be found containing glyphs for this range
documentLength ULONG 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: 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 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: 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.

Two new values for fill-opacity and stroke-opacity are defined: objectFillOpacity and 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 objectStroke and 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-width, stroke-dasharray, and 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.

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, scripting is disabled in the glyphs document.

Animation is enabled. (But not yet supported in Gecko.)

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. 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.