<canvas> APIsCanvaSVG is an experiment I am conducting to get a better idea of what you can and cannot do with the new <canvas> element suggested by the WHATWG. The current goal of CanvaSVG is to provide as much of a mapping of <canvas> functionalities using the SVG Tiny 1.2 grammar as possible. While ideally I could try to achieve full compliance with the Conforming Static SVG Tiny 1.2 Viewer conformance criterion, in other words implement the static graphic features of SVG Tiny 1.2 and leave out complex things like scripting and animation support.
That's a very legitimate question to ask. The claim has been made by people close to the source of all things <canvas> that those newly-introduced APIs were way, way, way easier to add to Safari than SVG. I begged to disagree then, and I disagree still today. Of course, the level of SVG integration that we are finally seeing in modern browsers today, such as Opera and Mozilla, is definitely a complex and lengthy endeavour. However, the argument of complexity of implementation for the level of functionlity offered by Apple with their <canvas> extension falls flat, as I think I'm showing with this effort. Basically, with a modern graphics platform underneath and a good XML foundation (Apple has both in place with Quartz2D APIs and libxml integration), then implementing a conformant static SVG viewer would not take more than a week to an experienced graphics programmer. Heck, I'm not that much of an experienced graphics programmer at all and it took me all in all like 3 days of programming to produce CanvaSVG, and that's only using <canvas> and Safari's Core DOM implementation as my platform.
Obviously, it can be argued that <canvas>, whatever happens, will be much faster at doing what it does than an equivalent implementation using SVG markup in-lieu of APIs. I don't think so. Of course, this puppy right here isn't really fast, and I never thought it would be. Before I can actually call <canvas> APIs, I have to go through parsing of the SVG markup using Safari's DOM Core implementation. I haven't done any benchmarks, but something tells me that the performance in that environment is not very good compared to what could be done using libxml straight away or even coming up with a customized parser in C. Basically, I think Apple would have done something just as fast with a static SVG Tiny implementation if done right. Usually the things that may make cost an SVG implementation performance-wise are things like maintaining a DOM alive and SMIL-based animation. A conforming static user agents wouldn't have to cater for any of that.
And even if there were a major speed difference, what would the gain be? What major use cases for <canvas> is there that would actually require this hypothetical speed difference? I can only think of very marginal use cases that would actually require drawing an immense number of graphics shapes. The disadvantages of <canvas> are however easy for me to enumerate (maybe it's because I'm biased). For one, what percentage of web authors have any idea how to use immediate graphics mode APIs such as <canvas>'s? Now compare that to the number of web authors that are familiar with markup languages and DOM APIs. I just don't think there is a good reason to do <canvas> when you can just do SVG instead.
I don't really blame Apple that much for doing <canvas>. I guess it was more from a purely programmatic and standards-adhering point of view that I was disappointed that Apple was introducing this new functionality, now picked up by the WHATWG, instead of picking an existing technology. I don't think many people are actually going to use <canvas> when most modern browsers (save probably for whatever IE7 turns out to be) already support (Opera 8, Firefox 1.1, Konqueror) or will be (most likely Safari) supporting SVG. Rant over, for more tune into Dean's insightful rant.
<canvas> code: I'd like to write a program that could be run on the server and compile an SVG fragment to a <canvas> element and the necessary API calls to render the SVG. No more reason to do that than doing CanvaSVG in the first place, but it'd be fun.<canvas> implementation in SVG: Someone told me that he'd like to use <canvas> APIs to generate SVG content and I might just do that someday. Same comment as the previous one.The two user agents I have been developing this code against are Safari 2.0 and Firefox 1.1. As far as I know, Safari 1.3 should also work, but I haven't tested it it. I also expect that any other user agent out there that uses recent WebCore and Gecko libraries will be able to render SVG using CanvaSVG.
I have one ugly test case that I have been writing as I was implementing SVG features, there are also the all-time classic lion and tiger for something that you can actually look at without going blind, although the tiger sample will render badly in Safari due to known issues in WebCore.
CanvaSVG.js.gz: all the ECMAScript classes needed in one gzipped file.
You can see all of the source code used for this project in full syntax colored glory:
<svg> elements and instantiates a CanvaSVGDocument for each.
<path> commands into corresponding <canvas> APIs.
transform attribute value into an array of individual commands.
viewBox and preserveAspectRatio attribute values.
Legend: SUPPORTED PARTIAL UNSUPPORTED
| Element | Attributes | Notes |
| svg | width | Percentages are unsupported |
| height | Percentages are unsupported | |
| viewBox | ||
| preserveAspectRatio | ||
| viewport-fill | ||
| viewport-fill-opacity | ||
| g | ||
| defs | ||
| use | x | |
| y | ||
| width | ||
| height | ||
| xlink:href | ||
| image | x | |
| y | ||
| width | ||
| height | ||
| xlink:href | Only for raster graphics | |
| switch | ||
| path | d | No arcs in SVG Tiny |
| rect | x | |
| y | ||
| width | ||
| height | ||
| rx | ||
| ry | ||
| circle | cx | |
| cy | ||
| r | ||
| ellipse | cx | |
| cy | ||
| rx | ||
| ry | ||
| line | x1 | |
| y1 | ||
| x2 | ||
| y2 | ||
| polyline | points | |
| polygon | points | |
| solidColor | solid-color | |
| solid-opacity | ||
| linearGradient | x1 | |
| y1 | ||
| x2 | ||
| y2 | ||
| gradientUnits | value objectBoundingBox unsupported |
|
| radialGradient | cx | |
| cy | ||
| r | ||
| gradientUnits | value objectBoundingBox unsupported |
|
| stop | offset | |
| stop-color | ||
| stop-opacity |
Legend: SUPPORTED PARTIAL UNSUPPORTED
| Attribute | Notes |
| display | |
| visibility | |
| transform | No matrices or skews due to <canvas> limitations |
| color | |
| fill | No currentColor |
| stroke | No currentColor |
| stroke-width | |
| fill-opacity | |
| stroke-opacity | |
| stroke-linecap | |
| stroke-linejoin | |
| stroke-miterlimit | |
| stroke-dasharray | <canvas> can't deal with that |
| stroke-dashoffset | <canvas> can't deal with that |
| opacity | <canvas> can't deal with that |
There is no support for scripting in CanvaSVG. However, with a little more standards compliance from user agents, Core DOM scripting could be partially implemented by registering an event listener for the DOMSubtreeModified event on the root <svg> element and then re-render the entire document. It would be quite a hack, but would work fine for most kind of usage of CanvaSVG.
There is no support planned for animation in CanvaSVG. The <canvas> functionalities are static and implementing an animation engine for this would be a tremendous amount of work for a project that is supposed to be a tiny little script wrapper.
<canvas> implementationsContext2D.bezierCurveTo method the prevents the correct drawing of cubic Béziers curves (i.e. the c, C, s and S SVG path commands won't work).
Context2D.quadraticCurveTo method doesn't actually exist, whereas another method called Context2D.quadraticCurveToPoint can be used in place.
Context2D.drawImage method and raster images in SVG won't work.
As of June 20th, and possibly earlier, there are no known issues with Mozilla Firefox as the sole bug I had listed (Context2D.globalAlpha not working) has been fixed.
viewBox, preserveAspectRatio, points, d and transform attributes. Kevin, you rock.
<canvas> APIs specification.
<canvas> documentation (or lack thereof).