W3C

SVG Glyphs in OpenType

Unofficial Editor’s Draft 1 February 2013

This Version:
http://dev.w3.org/SVG/modules/fonts/SVG-OpenType.html
Participate:
Send feedback to public-svgopentype@w3.org
Editors:
Edwin Flores, Mozilla Corporation <eflores@mozilla.com>
Cameron McCormack, Mozilla Corporation <cam@mcc.id.au>

Abstract

This document defines a new OpenType table that allows multi-colored, animated glyphs to be specified using SVG.

Status of This Document

This document is an Unofficial Editor’s Draft of the SVG Glyphs in OpenType specification, produced by the editors listed above. It is not yet a document that has been officially adopted by a W3C Working Group, although it is intended to be officially adopted by the W3C SVG Working Group or some other group at some point. Please send comments about this document to public-svgopentype@w3.org (archived).

Table of Contents

1. Introduction

This document proposes a way to define glyphs in OpenType fonts which can be colored or animated, or indeed support any existing feature of SVG’s secure animated mode. This is achieved by defining a new OpenType table containing SVG documents which include glyph definitions in SVG.

Conformance requirements are expressed with a combination of descriptive assertions and RFC 2119 terminology. The key words “MUST”, “MUST NOT”, “REQUIRED”, “SHALL”, “SHALL NOT”, “SHOULD”, “SHOULD NOT”, “RECOMMENDED”, “MAY”, and “OPTIONAL” in the normative parts of this document are to be interpreted as described in RFC 2119. However, for readability, these words do not appear in all uppercase letters in this specification.

All of the text of this specification is normative except sections explicitly marked as non-normative, examples, and notes. [RFC2119]

Two conformance classes are defined: conforming fonts and conforming implementations. Conformance requirements on fonts are authoring conformance requirements. Violating an authoring conformance requirement has no affect on how an implementation processes an OpenType font with SVG glyphs unless otherwise stated with requirements on conforming implementations.

2. The SVG table

An OpenType table with the tag “SVG ” – hereafter called the SVG table – is used as an index to point to an embedded SVG document within the table that defines SVG glyphs for glyph IDs within a specified range. The table consists of a header, followed by an index, and then a number of SVG documents. The table format uses the data types and contentions used in the OpenType specification. [OPENTYPE]

2.2. Glyph document index

Each index entry specifies a range [startGlyphId, endGlyphId] of glyph IDs and the location of the associated SVG document in the font relative to the start of the SVG table. Each glyph ID in the range may, but need not, have a glyph definition in the document.

Name Type Description
startGlyphId USHORT The first glyph ID in the range described by this index entry.
endGlyphId USHORT The last glyph ID in the range described by this index entry.
documentOffset ULONG The offset of the SVG document, in bytes, into the font relative to the beginning of the SVG table.
documentLength ULONG The length of the SVG document, in bytes.

Index entries may have equal (documentOffset, documentLength) pairs, but the ranges must not otherwise intersect. The startGlyphId in an index entry must be less than or equal to endGlyphId, and the [startGlyphId, endGlyphId] ranges across all of the index entries must not overlap.

Implementations must ignore the entire SVG table if it contains index entries with invalidly intersecting byte ranges, mis-ordered start and end glyph IDs or overlapping glyph ID ranges.

3. SVG documents

Following the header section is a series of UTF-8 encoded SVG documents.

The SVG documents are largely standard SVG with some extensions for SVG glyphs. Two new attributes are defined to map glyph IDs to elements, either of which can be used on graphics elements and container elements.

Each SVG document identified by a (documentOffset, documentLength) pair must be a well-formed XML 1.0 document that is a conforming SVG 2 stand-alone files.

It might be better to reference SVG 1.1, given that SVG 2 is still in development.

An SVG document must be parsed with a non-validating XML 1.0 parser. [XML10] If a document fails to parse, or if it successfully parses its document element is not the “svg” element in the SVG namespace “http://www.w3.org/2000/svg”, or if uses any encoding other than UTF-8, then the document is ignored and considered not to contain any SVG glyph definitions.

Each successfully loaded SVG document must be processed in secure animated mode. [SVGINTEGRATION] The SVG document therefore will not be able to resolve any external resources or run any script.

All animation timelines across all SVG documents in SVG tables must be synchronized with a timeline start appropriate for the kind of animation as if they ran directly in the document using the font. For example, the timeline for SVG animation elements would all begin with t = 0s at the time the referencing document’s load event is dispatched. When rendering glyphs to media that do not support animation, the SVG documents must be processed without applying any animations, not by rendering them with animations applied but at a particular snapshot time.

3.1. SVG glyph definitions

To associate elements in the document with glyph IDs, two new attributes are defined for use on graphics elements and container elements: glyphchar and glyphid.

Name Value Lacuna value Animatable
glyphchar see below N/A no

The value of a glyphchar attribute must be a single Unicode character followed by an optional Unicode Variation Selector (UVS). [UNICODE6] This value is mapped to a glyph ID via the CMAP table of the typeface. By specifying this attribute on a graphics element or container element, it indicates that the element is the definition of the SVG graphics for the corresponding glyph ID. The attribute must not be specified on any other element.

Name Value Lacuna value Animatable
glyphid <integer> N/A no

The value of a glyphid attribute must be an integer in the range [0, 65535] and represents a glyph ID. By specifying this attribute on a graphics element or container element, it indicates that the element is the definition of the SVG graphics for the corresponding glyph ID. The attribute must not be specified on any other element. Specifying the glyph ID directly with glyphid, and not with a glyphchar attribute, can be useful for glyph substitutions via, for example, the GSUB table.

If an element has both a glyphchar and a glyphid attribute, then glyphchar must be ignored. If these attributes have a specified value that does not match the required syntax, then the element is considered not to define a glyph, as if the attributes were not specified. A given SVG document embedded in the SVG table must not define more than one element for a given glyph ID; if it does, then the first in document order must be used. If the attributes are specified on an element other than a graphics element or container element, then the glyph will be considered to be defined but will not have any graphical content.

It is important to note that as the CMAP table is used to resolve glyph IDs, the font should contain “legacy” outlines to fall back on for user agents which do not yet support this feature, and for rendering glyphs in contexts where an outline glyph is required, for example in a clipPath element.

We should go into more detail about known situations where the plain glyphs will be used instead of the SVG glyphs.

SVG glyphs have a baseline of y = 0 and a height of 1000 user units. The coordinate system is “y-down”, in contrast to the “y-up” coordinate system used in SVG Fonts but not in the rest of SVG. (Note that the ascent will be negative in the element’s coordinate system.) Other coordinate spaces can be chosen by using an svg element with a viewBox attribute as the element defining the glyph. Note that transforms on ancestor elements of the element defining a glyph do not have an effect on the position of the graphics within the glyph’s em box.

All other metrics are defined in the usual OpenType manner.

Consider the following SVG glyph document used in a font where the glyphs for “A” and “B” both have an ascent of 800 and an advance of 100:

<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100" width="400" height="400">
  <g transform="rotate(45)">
    <g glyphchar="A">
      <path d="M 0,200 h 100 v -1000 h -100 z"/>
    </g>
    <svg glyphchar="B" viewBox="0 0 10 100" width="100" height="1000">
      <path d="M 0,20 h 10 v -100 h -10 z"/>
    </svg>
  </g>
</svg>

Despite the use of the viewBox, width and height attributes on the outermost svg element and the transform attribute on the outer g element, the path defining the shape of the “A” glyph exactly traces the outside of the glyph’s em box.

The “B” glyph is defined to look identical to the “A” glyph, but it uses an svg element with a viewBox attribute to change the coordinate system used by the path element.

3.2. Inherited context styles

This section extends some SVG styling properties with values that inherit from the context text object. In Web content, the context text object is the CSS box (for HTML or similar content) or SVG text content element that references the font and defines the text to render using the SVG glyphs. Note that a user agent style sheet is used to make glyphs default to inheriting fill and stroke context styles from context text object.

3.2.1. The ‘context-value’ value

The ‘stroke-width’, ‘stroke-dasharray’ and ‘stroke-dashoffset’ properties are extended to allow a new value context-value.

Name: stroke-width, stroke-dasharray, stroke-dashoffset
New Value: context-value

The context-value value represents the value of the given property on the context text object scaled in such a way that it has the same size in the glyph’s coordinate system. Since the height of the em box of all SVG glyphs is 1000 user units, the scale factor is:

scale = 1000 ÷ font_size

where font_size is the value of the ‘font-size’ property on the context text object in px.

Consider the following SVG document:

<svg xmlns="http://www.w3.org/2000/svg">
  <text x="100" y="100" font-family="Fancy Font" font-size="0.5in" stroke-width="2px">A</text>
</svg>

Assume that “Fancy Font” refers to an OpenType font with the following SVG glyph:

<svg xmlns="http://www.w3.org/2000/svg">
  <g glyphchar="A">
    <g transform="scale(0.5)">
      <path d="..." stroke-width="context-value"/>
    </g>
  </g>
</svg>

0.5in is equal to 48px. Thus, the scale factor to use is 1000 ÷ 48, resulting in the effective value of the context-value value being 2px × 1000 ÷ 48 ≃ 41.667px. Note that the transform on the g element has no effect in determining the effective value of the context-value value.

3.2.2. The ‘context-fill’ and ‘context-stroke’ values

The <paint> and <color> data types are extended to allow new values context-fill and context-stroke.

Name: <paint>, <color>
New Value: context-fill | context-stroke

When the context-fill or context-stroke values are used as the value of a property that takes a <paint>, the effect is as if the value of the ‘fill’ or ‘stroke’ property (respectively) on the context text object were used, except that any SVG paint server is painted in the coordinate system of the context text object rather than the coordinate system of the element on which context-fill or context-stroke were specified. If the paint server uses any values relative to the bounding box of the element it is applied to (for example by specifying ‘objectBoundingBox’ for the patternUnits attribute on a pattern element), then these are resolved against the bounding box of the context text object.

Should we allow a fallback color to be specified after context-fill or context-stroke?

When the context-fill or context-stroke values are used as the value of a property that takes a <color>, the visual effect is as if the solid color component of the ‘fill’ or ‘stroke’ property (respectively) on the context text object were used. Solid color components include the basic and extended color keywords, RGB and RGBA color values, the transparent color keyword, HSL and HSLA color values, the currentColor color keyword, the CSS2 system colors from CSS Color Module Level 3 ([CSS3COLOR], section 4) and ICC, LAB, ICC named colors and uncalibrated device colors from SVG 2 ([SVG2], chapter 12). If the context paint value is a paint server reference with no fallback solid color or a CSS gradient value, then the visual effect is as if transparent were used.

Consider the following document:

<svg xmlns="http://www.w3.org/2000/svg">
  <linearGradient id="g" x1="0" y1="0" x2="1" y2="0">
    <stop offset="0" stop-color="red"/>
    <stop offset="1" stop-color="yellow"/>
  </linearGradient>
  <text x="100" y="150" font-family="Simple Font" font-size="100px" fill="url(#g) orange">AAA</text>
</svg>

Assume that “Simple Font” refers to an OpenType font with the following SVG glyph that has both an ascent and an advance of 800:

<svg xmlns="http://www.w3.org/2000/svg">
  <g glyphchar="A">
    <circle cx="400" cy="-400" r="300" fill="none" stroke="context-fill" stroke-width="100px"/>
  </g>
</svg>

The use of context-fill as the value of ‘stroke’ on the glyph’s circle element will result in the linear gradient being sized to the context text object. The document would render approximately like the following:

3.2.3. The ‘context-fill-opacity’ and ‘context-stroke-opacity’ values

The ‘fill-opacity’, ‘stroke-opacity’ and ‘opacity’ are extended to allow new values context-fill-opacity and context-stroke-opacity.

Name: fill-opacity, stroke-opacity, opacity
New Value: context-fill-opacity | context-stroke-opacity

The effect of the context-fill-opacity and context-stroke-opacity values is to take on the value of the ‘fill-opacity’ or ‘stroke-opacity’ property (respectively) on the context text object, with the exception that if the ‘fill’ or ‘stroke’ property (again, respectively) has the value none, then the effective opacity value will be 0.

Consider the following SVG document:

<svg xmlns="http://www.w3.org/2000/svg" width="350" height="200">
  <text x="100" y="120" font-family="Accented I" font-size="100px">
    i
    <tspan fill="none" stroke="olivedrab" stroke-width="2px">i</tspan>
    <tspan fill="indigo" fill-opacity="0.5">i</tspan>
  </text>
</svg>

Assume that “Accented I” refers to an OpenType font with the following SVG glyph that has ascent of 800 and an advance of 500:

<svg xmlns="http://www.w3.org/2000/svg">
  <g glyphchar="i">
    <path d="M 100,-400 h 200 v 350 h 100 v 50 h -300 v -50 h 100 v -300 h -100 z"/>
    <circle cx="240" cy="-530" r="50" fill="none"
            stroke="red" stroke-width="30px" stroke-opacity="context-fill-opacity"
            stroke-dasharray="none"/>
    <circle cx="240" cy="-530" r="15" fill="none"/>
    <circle cx="240" cy="-530" r="75" fill="none"/>
  </g>
</svg>

The glyph defines a lowercase “i” that has a red stroked circle forming the dot above the base of the letter. Since we want to consider the stroke of the red circle to effectively be part of the filled shape of the glyph, we use the context-fill-opacity value for its ‘stroke-opacity’ property. We also set its ‘stroke-dasharray’ property to none so that dashed strokes do not affect it. The two following circles are used to define the path to stroke if the text using the glyph is stroked. Those circles have ‘fill’ set to none so that any fill paint on the text is not used.

The SVG document would be rendered as follows:

Notice that due to the special behavior of context-fill-opacity being equivalent to 0 when the context text object’s ‘fill’ is none, the red circle in the second “i” is not rendered.

Are all of these new values sufficiently motivated? For cases where we need to define a separate region in a glyph to be stroked, we might be able to use the regular OpenType outline. However, it could be that this outline, although suitable for fallback, is different enough from the SVG glyph that it makes sense to be able to define the stroking region in the SVG glyph itself.

3.3. User agent style sheet

The following user agent style sheet must be applied to SVG documents processed from the SVG table:

:root {
   fill: context-fill;
   fill-opacity: context-fill-opacity;
   stroke: context-stroke;
   stroke-opacity: context-stroke-opacity;
   stroke-width: context-value;
   stroke-dasharray: context-value;
   stroke-dashoffset: context-value;
}

4. Acknowledgements

The editors wish to thank Robert O’Callahan and Sairus Patel for their input into this specification.

5. References

Normative references

[CSS3COLOR]
Tantek Çelik; Chris Lilley; L. David Baron. CSS Color Module Level 3. 07 June 2011. W3C Recommendation. URL: http://www.w3.org/TR/css3-color/
[OPENTYPE]
OpenType specification, Microsoft. URL: http://www.microsoft.com/typography/otspec/default.htm
[RFC2119]
S. Bradner. Key words for use in RFCs to Indicate Requirement Levels.. Internet RFC 2119. URL: http://www.ietf.org/rfc/rfc2119.txt
[SVG2]
Nikos Andronikos; et al. Scalable Vector Graphics (SVG) 2. 28 August 2012. W3C Working Draft. (Work in progress.) URL: http://www.w3.org/TR/SVG2/
[SVGINTEGRATION]
Doug Schepers. SVG Integration 1.0. 01 October 2010. W3C Editor’s Draft. (Work in progress.) URL: http://dev.w3.org/SVG/modules/integration/SVGIntegration.html
[UNICODE6]
The Unicode Consortium. The Unicode Standard, Version 6.2.0. Defined by: The Unicode Standard, Version 6.2.0. URL: http://www.unicode.org/versions/Unicode6.2.0/
[XML10]
Tim Bray; et al. Extensible Markup Language (XML) 1.0 (Fifth Edition). 26 November 2008. W3C Recommendation. URL: http://www.w3.org/TR/2008/REC-xml-20081126/