Sat, 10 Oct 2009

Fun and No-Fun with SVG


Permanent link

Lately I've been playing a lot of with SVG, and all in all I greatly enjoyed it. I wrote some Perl 6 programs that generate graphical output, and being a new programming language it doesn't have many bindings to graphic libraries. Simply emitting a text description of a graphic and then viewing it in the browser is a nice and simple way out.

I also enjoy getting visual feedback from my programs. I'd even more enjoy it if the feedback was more consistent.

I generally test my svg images with three different viewers: Firefox 3.0.6-3, inkscape (or inkview) 0.46-2.lenny2 and Opera 10.00.4585.gcc4.qt3. Often they produce two or more different renderings of the same SVG file.

Consider this seemingly simple SVG file:

<svg
    width="400"
    height="250"
    xmlns="http://www.w3.org/2000/svg"
    xmlns:svg="http://www.w3.org/2000/svg"
    xmlns:xlink="http://www.w3.org/1999/xlink"
    style="background-color: white"
>

    <defs>
        <path id="curve"
              d="M 20 100
                 C 60 30
                 320 30
                 380 100"
              style="fill:none; stroke:black; stroke-width: 2"
        />
   </defs>
   <text font-size="40" textLength="390" >
        <use xlink:href="#curve" />
        <textPath xlink:href="#curve">SPRIXEL</textPath>
   </text>
</svg>

If your browser supports SVG, you can view it directly here.

This SVG file first defines a path, and then references it twice: once a text is placed on the path, the second time it is simply referenced and given some styling information.

Rendered by Firefox:

rendered by firefox

Rendered by Inkview:

rendered by inkview

Rendered by Opera:

rendered by opera

Three renderers, three outputs. Neither Firefox nor Inkview support the textLength attribute, which is a real pity, because it's the only way you can make a program emit SVG files where text is guaranteed not to overlap.

If you scale text in Inkscape and then put it onto a path, the scaling is lost. I found no way to reproduce opera's output with inkscape without resorting to really evil trickery (like decomposing the text into paths, can then cutting the letters apart and placing them manually). (Equally useful is the dominant-baseline attribute, which Inkscape doesn't support either).

The second difference is that only Firefox shows the shape of the path. Firefox is correct here. The SVG specification clearly states about the use attribute:

For user agents that support Styling with CSS, the conceptual deep cloning of the referenced element into a non-exposed DOM tree also copies any property values resulting from the CSS cascade [CSS2-CASCADE] on the referenced element and its contents. CSS2 selectors can be applied to the original (i.e., referenced) elements because they are part of the formal document structure. CSS2 selectors cannot be applied to the (conceptually) cloned DOM tree because its contents are not part of the formal document structure.

Sadly it seems to be a coincidence that Firefox works correctly here. If the styling information is moved from the path to the use element the curve is still displayed - even though it should not be.

Using SVG feels like writing HTML and CSS for 15 year old browsers, which had their very own, idiosyncratic idea of how to render what, and what to support and what not.

Just like with HTML I have high hopes that the overall state will improve; Indeed I've been told that Firefox 3.5 now supports the textLength attribute. I'd also love to see wide-spread support for SVG animations, which could replace some inaccessible flash applications.

[/misc] Permanent link