Skip to content

Commit

Permalink
Use old school data URIs for generating image if it helps working aro…
Browse files Browse the repository at this point in the history
…und tainted canvas issues. Closes #88
  • Loading branch information
cburgmer committed Feb 6, 2015
1 parent 8898d01 commit 5deb107
Showing 1 changed file with 76 additions and 9 deletions.
85 changes: 76 additions & 9 deletions src/svg2image.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,51 @@ var svg2image = (function (ayepromise, window) {

var module = {};

var urlForSvg = function (svg, useBlobs) {
if (useBlobs) {
return URL.createObjectURL(new Blob([svg], {"type": "image/svg+xml"}));
} else {
return "data:image/svg+xml;charset=utf-8," + encodeURIComponent(svg);
}
};

var simpleForeignObjectSvg = '<svg xmlns="http://www.w3.org/2000/svg" width="1" height="1"><foreignObject></foreignObject></svg>';

var supportsReadingObjectFromCanvas = function (url) {
var canvas = document.createElement("canvas"),
image = new Image(),
defer = ayepromise.defer();

image.onload = function () {
var context = canvas.getContext("2d");
try {
context.drawImage(image, 0, 0);
// This will fail in Chrome & Safari
canvas.toDataURL("image/png");
defer.resolve(true);
} catch (e) {
defer.resolve(false);
}
};
image.src = url;

return defer.promise;
};

var readingBackFromCanvasBenefitsFromOldSchoolDataUris = function () {
// Check for work around for https://code.google.com/p/chromium/issues/detail?id=294129
return supportsReadingObjectFromCanvas(urlForSvg(simpleForeignObjectSvg, true))
.then(function (supportsReadingFromBlobs) {
if (supportsReadingFromBlobs) {
return false;
}
return supportsReadingObjectFromCanvas(urlForSvg(simpleForeignObjectSvg, false))
.then(function (s) {
return s;
});
});
};

var supportsBlobBuilding = function () {
if (window.Blob) {
// Available as constructor only in newer builds for all browsers
Expand All @@ -14,18 +59,39 @@ var svg2image = (function (ayepromise, window) {
return false;
};

var useBlobs = supportsBlobBuilding() && window.URL;
var checkBlobSupport = function () {
var defer = ayepromise.defer();

var buildImageUrl = function (svg) {
if (useBlobs) {
return URL.createObjectURL(new Blob([svg], {"type": "image/svg+xml"}));
if (supportsBlobBuilding && window.URL) {
readingBackFromCanvasBenefitsFromOldSchoolDataUris()
.then(function (doesBenefit) {
defer.resolve(! doesBenefit);
});
} else {
return "data:image/svg+xml;charset=utf-8," + encodeURIComponent(svg);
defer.resolve(false);
}

return defer.promise;
};

var checkForBlobsResult;

var checkForBlobs = function () {
if (checkForBlobsResult === undefined) {
checkForBlobsResult = checkBlobSupport();
}

return checkForBlobsResult;
};

var buildImageUrl = function (svg) {
return checkForBlobs().then(function (useBlobs) {
return urlForSvg(svg, useBlobs);
});
};

var cleanUpUrl = function (url) {
if (useBlobs) {
if (url instanceof Blob) {
URL.revokeObjectURL(url);
}
};
Expand All @@ -43,8 +109,6 @@ var svg2image = (function (ayepromise, window) {
}
};

url = buildImageUrl(svg);

image = new window.Image();
image.onload = function() {
resetEventHandlers();
Expand All @@ -58,7 +122,10 @@ var svg2image = (function (ayepromise, window) {
// Webkit calls the onerror handler if the SVG is faulty
defer.reject();
};
image.src = url;
buildImageUrl(svg).then(function (imageUrl) {
url = imageUrl;
image.src = url;
});

return defer.promise;
};
Expand Down

0 comments on commit 5deb107

Please sign in to comment.