Capture most Canvas output in a printable, scalable, PostScript file
Apple's OSX uses 'Display PostScript', which derives from the Adobe printer language PostScript. When it came time to design Dashboard, Apple added a special hook from the HTML based widgets to the Display PostScript system and called it the canvas tag. The JavaScript API and basic programming model of the canvas tag roughly correspond to PostScript. So, it becomes fairly easy to make a new canvas context type that captures it's output to PostScript file.
Works fully in FireFox (3.0.4). Safari (3.2.1) runs but doesn't support getImageData for raster images. Opera (9.52) seems to produce PostScript okay, but it's in-browser canvas is still broken, of course. IE doesn't even support canvas...
Live Demo
The rough way to test the output is by copy-pasting the results into a .eps file, and then running ps2pdf to create a PDF, which gets launched in the OSX Preview.app. Any other use of GhostScript or another PostScript parser should also work, in theory.
There is also a patch queue (BitBucket, which seems to be down at the moment) on Philip Taylor's canvas tests. However, this testing process is still in need of documentation. You'll need at least Python (for the test generation), Firefox to run the tests, and ImageMagick to convert the .eps to .png
Download
Differences and Limitations
Things that cannot be implemented by postscript:
- The image API (getImageData and friends) makes no sense, and is unsupported.
- Canvas save/restore is specified to leave the current path unaffected, however in postscript gsave/grestore do preserve the path.
- Alpha is unsupported in postscript, which really stinks.
- globalCompositeOperator is a pixel operation, and is unsupported.
- Shadows would require both alpha and pixel operations. Beyond that, they are an Apple extension designed for their own use, which unfortunately made it into the spec.
- clearRect can't be implemented in a general way. As a special case, it might be possible to detect full-screen clears and just scrap everything. However, this gets complicated when transforms are involved.
- Executing lineTo without a path does nothing in canvas; Ghostscript for one will halt with an error. In principle a work around would be to track the path state myself, but since drawing without a path is silly, I'm not going to support it.
- Canvas arcTo specifies infinite lines under certain collinear circumstances. Postscript arct doesn't.
- Canvas specifies that zero-length lineTo segments are removed before stroking. Postscript quite happily draws endcaps, etc.
- isPointInPath could be evaluated by the PS interpreter, but we're just recording commands for later, so this is impossible (barring complete software emulation of paths)
Appear to be Ghostscript bugs:
- Using a fat stroke on arc less than full circle will extend slightly around a connecting point.
- Arc: lineWidth greater than radius creates a sun ray effect on the opposite side.
Potentially messy topics that haven't been implemented yet:
- fillStyle = 'transparent' (and equivalently, alpha 0.0) are not implemented, though in principal they could be, by state tracking.
- Gradients and patterns are are not yet implemented; in principle postscript supports them, but I've put off a potentially messy topic.
Features that might possible be supported using browser-specific features:
- Properties like strokeStyle and globalAlpha are just plain old JS properties, so they stay what you set them to; canvas is supposed to ignore out-of-range alpha values, for instance.
- drawImage depends on browser canvas support to get at the pixel data. So it's a no-go in IE, and Firefox 3.0 doesn't support animated images.
Known Bugs
- Bug
- The JS require script works okay on local files, but seems to run into first (second, third...) load problems when running over the net. You may have to hit reload a few times.
- Bug
- There needs to be a method to download the postscript file directly.
- Sweet Dreams
- In principle, direct PDF output would also be possible.