SVG Secrets

Peter Sorotokin
Adobe Systems Inc.
345 Park Ave
San Jose, CA 95110-2704

E-mail: mailto:psorotok@adobe.com

Abstract and Introduction

As any software developer knows, one frustrating rule is that 80% of the code goes to implement 20% of the most obscure features or their combinations. In the course of the Adobe SVG Viewer development I had my fair share of the 80%, but it seems that at least some of these features deserve better publicity. Most of them are completely standard, well-defined by the SVG 1.0 spec and implemented in SVG Viewer v3, yet not used as widely as I think they could be. This paper aims to bring SVG developer's attention to these features, but it by no means can provide all necessary details.

SVG Viewer usage

SVG Viewer as a Component

One of the biggest strength of "SVG the Standard" is that it naturally integrates with wide range of other technologies. Consequently, SVG renderer is the most useful if packaged as a component, rather then standalone product. This is not really the case with Adobe SVG Viewer, however, which was developed mostly as a plug-in and not a universal component. However, since any ActiveX control can be used as a component, at least to some degree, it is possible to do more with it then just embed SVG somewhere on a web page. Still, it is better to always wrap Adobe SVG Viewer in the Web Browser control.

Using from Windows Script Host

Roughly speaking, Windows Script Host is a way to run various scripting languages on Windows without any security restrictions imposed by the browser. Windows has two commands: wscript and cscript that allow one to run JScript (or VBScript) standalone (in either windowed or console environment). Adobe SVG Viewer can easily be used in such environment. The easiest way is to create an instance of Internet Explorer and place an embed tag with type image/svg+xml in it.

Use this link to load sample JavaScript file to be run by Windows Script Host.

Using from HTA

HTA stands for "HTML Application". It is essentially an HTML file with a script that has no security restrictions imposed on it. Such files can be run from the local filesystem (by double-clicking on them), but not from the Internet. Again, embed tag is an easy way to make use of the Adobe SVG Viewer.

Use this link to load sample HTA file.

Quality Issues

Imperfect Antialiasing

This problem is not inherent to SVG, but to implementations (including Adobe SVG Viewer). Perfect antialiasing can be done by rendering complete artwork at a much higher resolution and subsequent downsampling. In most implementations, however, antialiasing is done on a per-shape basis, not for the whole artwork. This can produce unexpected results, which are especially noticeable when two shapes share a common edge. In most cases extending one of the shapes slightly can solve this problem, but no generic method exists.

Click here to see example. Look for thin white and black lines. See how they are not affected by zooming. Also notice that when antialiasing is turned off, these artifacts disappear.

Text Readability

It is well-known facts in font design that for small font sizes readability conflicts with scalability. To improve text readability for small font sizes one can set text-rendering to "optimizeLegibility", but beware that for most TrueType fonts this will cause text to be slightly non-scalable, because spacing between glyphs will be set in the resolution-dependent manner. I strongly recommend using this setting for all long passages of text with font size smaller then 14 pixels.

Click here to see example. Click on the text to loop through all possible values for text-rendering property. Try zooming in or out.

Media Type

Version 3 of Adobe SVG Viewer supports CSS rules for specific media type. For instance, it is trivial to make UI controls invisible when printing by using CSS "noPrint" class defined this way:

@media print {
  .noPrint { display:none; }
}

Performance issues

Transparency

Transparency is an expensive feature, but this is especially true for the group transparency (which is defined by opacity property). Fill and stroke transparency are much cheaper. If you can, try to experiment with fill-opacity and stroke-opacity properties instead of plain opacity.

Antialiased Clip

Antialiased clip can be fairly expensive. Always turn off antialiasing for clipPath element if you can (by setting shape-rendering and text-rendering to optimizeSpeed).

Stroke vs. Fill

Stroke is computationally expensive operation. If you can, use fill, instead of stroke, even if it makes your shape more complex (this might require some experiments).

NodeList::item

Do not use this API to loop through all the child nodes of an element. It is much more efficient to do this:

for( var ch = element.firstChild ; ch ; c = ch.nextSibling )
{
  ...
}

Using pointer-events

Sometimes an element should not draw, but should handle events. SVG defines pointer-events property that handles this case nicely and can be much more efficient then setting opacity to 0. Simply set pointer-events to "fill" and fill to "none". Sometimes, the opposite is desired: visible element that does not consume events. Setting pointer-events to "none" handles this need.

If you dig into SVG Scrollbar code, you will see how it creates big invisible rectangle that covers all the artwork when scrolling is active, so that text does to get accidentally selected

Optimization of Animated/Interactive Graphics

In most practical situations the cost of drawing is much bigger then the cost of making all the DOM calls, applying animations, etc. To improve performance consider these two questions:

Text Layout

Keep text a text

This seems obvious, but unfortunately in many cases I saw people giving up on "textness" of text to preserve visual appearance. The matter of fact is that in SVG one is simply never have to face this tradeoff at all. The fundamental strength of SVG is that if something is text, it can be represented as text, no matter what the appearance is. (Well, this is not yet true for all the writing systems, but it holds for most of them, including all Western languages, Japanese and Chinese).

Absolute positioning

Avoid breaking up text in multiple text elements. Arbitrary positioning can be achieved with x, y and rotate attributes and scaling can be done with font-size property.

SVG Fonts

Custom font faces can be represented with SVG fonts, even if it involves multi-color designs, opacity or filter effects.

Alternate glyphs

Things like logos can easily be represented by alternate glyphs. This approach provides the advantage of the text being text (including text selection and search), allowing absolutely arbitrary appearance.

Tref Element

Authors can reuse the content of their desc and title elements (or, for that matter, any element in their private namespace) by using tref element. This element is just like tspan, but it "borrows" its text content from arbitrary other element.

Here is a simple implementation of tooltips that utilizes capabilities of tref element to extract "textual" content of an element.

Scripting

EventTarget::addEventListener

If you want to learn just a single ECMAScript API and you do not know this one yet, be sure to learn it! It seems like you can always do what you want with onfoo="bar" attributes, but this method is much more flexible. You can add and remove event listeners as needed, you can have many listeners for the single event, you can "capture" events and you can attach custom data to your event listeners. In Adobe SVG Viewer implementation, the second parameter to this call can be either a function or an object that has handleEvent method; it cannot be a string.

currentScale and currentTranslate

Top-level <svg> element has two very useful ECMAScript attributes: currentScale and currentTranslate. They correspond to the viewer's zoom and pan settings. Two very iseful things can be done with them. First, a script can read them to find out current settings and adjust the drawing accordingly, i.e. to have map legend float always on the same spot or adjust line thickness. (To keep track of the changes to these attributes, one can set up event listeners for SVGScroll and SVGZoom events). Secondly, a script can modify them, therefore performing zoom and pan programmically. This might seem like not a big deal, since it already can be done using transform attribute, but viewer's built-in zoom and especially pan can be much more efficient.

SVG Scrollbar that I uploaded to the svg-developers group can serve as a complete example of using this technique (as well as SVG zoom, scroll and resize events). Simpler example can be found here - compare perfomance of simply dragging letters around and doing the same thing with the Shift key pressed.

SVGZoom, SVGScroll and SVGResize events

These events are handy when part of the SVG document should not be affected by zoom and pan or should change location or size on resize (for instance, map legend or UI control such as scrollbar). Once can simply use transform attribute to compensate for changes of initial CTM due to zoom and pan. SVGZoom event is raised every time currentScale changes on top-level svg element and SVGScroll is raised every time currentTranslate is changed. Once can use either addEventListener API or onzoom, onscroll and onresize attributes to set up listeners for these events.

pause/unpause/setCurrentTime/getCurrentTime

If you need to control the animation timeline from a script, these three methods are very useful. It is trivial to use them and they do exactly what you would think they do. And setCurrentTime does work (and has a visual effect) even if animation is paused! In Adobe SVG Viewer pause/unpause are tied up with corresponding context menu item. Unfortunately, in v3 they are implemented only for the top-level <svg> element.

Document variable

It is hard to say if this is a standard or an extension, but Adobe SVG Viewer v3 does define document variable that points to the SVG Document node. It is a mere convenience, of course, as owning document always can be obtained from the event object.

Using custom namespaces

Currently, SVG spec does not allow users to define their own custom elements. However, some degree of customization of SVG language can be done with smart usage of scripting and custom namespaces. For instance, it is fairly easy to define some sort of macro language using this approach: script can search for all elements in the given namespace and substitute them in the DOM tree with real SVG elements. Or some private data can be stored in the custom attribute and used by a generic event listener.

Here is a simple example of using custom namespace to define "SVG macros". It also illustrates using "document" variable, EventTarget::addEventListener method and defining an EventListener interface.

Adobe-specific Features

AdobeSVGViewer Processing Instruction

Adobe SVG Viewer accepts a special XML processing instruction:

<?AdobeSVGViewer [resolution="number"] [save="no|snapshot|original"]?>

resolution (in dots per inch) is used when rasterizing SVG document for devices with unknown resolution. It is used, for instance, when printing in IE5.5+ (IE converts ActiveX controls to a metafile, not allowing them to access printer directly). Value of the "save" parameter controls "Save As..." menu item: value "original" is default and causes original SVG file to be saved; value "snapshot" will cause snapshot of the DOM to be saved and value "no" will disable "Save As..." and "Copy SVG" menu items.

Interaction between Scripts in HTML and SVG

Each SVG embedded in HTML has its own ECMAScript "window" (global) object which can be accessed using getWindow() call. All functions and variables defined on global level in SVG can be accessed through this object. This is very similar to accessing objects in different HTML frames. Vise versa, HTML "window" (global) object can be accessed throgh parent variable from svg scripts. Note that this link is subject to normal security restrictions: only files from the same domain can access earch other's global objects. In version 3 of the Viewer there is no way to relax this restriction.

Compressing Scripts and Stylesheets

Adobe SVG Viewer accepts gzip-compressed scripts and CSS stylesheets. This gets detected automatically and no special server configuration is needed.

Miscellaneous Features

A lot of other features are described in some detail at the svg-wiki site (at http://www.protocol7.com/svg-wiki). It is worth the read if you are OK with using proprietary extensions. Some features are:


Valid XHTML 1.0!