qrohlf / trianglify

Algorithmically generated triangle art
http://qrohlf.com/trianglify/
GNU General Public License v3.0
10.08k stars 669 forks source link

Add PNG download option #1

Closed tdhsmith closed 10 years ago

tdhsmith commented 10 years ago

Adds basic PNG download link by writing the SVG to an invisible canvas and generating a PNG data URI. This only changes the index page, and not trianglify,js, but the same approach could be added there if desired.

Might be broken for older browsers due to restrictions on tainted canvases, but I suspect supporting them would require a totally different approach..?

qrohlf commented 10 years ago

Nice work!

Couple of things:

tdhsmith commented 10 years ago

I don't have enough Canvas know-how to guess why it's happening right now, but I'll happily bust out my Mac environment to check it out later tonight. (& rebase) :smile:

tdhsmith commented 10 years ago

Ok I checked it out on Safari 5.1.7 and 4.1.4 (multi) on Snow Leopard and both of them throw DOM Security Error 18. Sadly this is exactly the sort of "restriction on tainted canvases" that "requires a totally different approach".

The SE question "Rasterizing an in-document SVG to Canvas" addresses most of the matter, but I learned quite a bit, so I wanted to write my own summary if anyone finds it useful:

The canvas element has to deal with security whenever it loads an external image. For exmple, a malicious entity could store a script within image data and then load it through a canvas. Normally this risk is mitigated by only allowing images from the same domain and those loaded with Cross-Origin Resouce Sharing. Since this restriction would affect a lot of developers who were just trying to do perfectly innocuous things, browsers also provide a compromise: loading unsafe image resources is allowed, but it "taints" the canvas, essentially making it write-only and forever blocking all methods that could get data out of the canvas. (This includes our dear toDataUrl())

So far, we should be in the clear; content in a data URL is considered to have the same origin as the script that generated it (WhatWG specification), so our SVG should be local. Unfortunately SVG files are particularly tricky because they can contain other images or arbitrary non-image content via the tag. (Robert Longson points out on SE that an SVG could contain links to be rendered by the browser, whose color could be examined by a malicious website to determine what sites the user has visited!) Therefore most browsers simply tainted canvases with any SVG content. Recently, most implemented finer-grained checks:

Barring security exploits, it's unlikely there is a solution to natively load SVGs and read their data in older browsers, save using a library capable of parsing SVG manually (i.e. canvg).

tdhsmith commented 10 years ago

That said, we're building our SVG by hand with rather simple rules, so we can sidestep the whole issue by adding a draw-direct-to-canvas method to trianglify.js.

I'll close this pull request for now and play around with that alternative.