Prefer native svg rendering if available

This commit is contained in:
Niklas von Hertzen 2014-09-08 21:16:30 +03:00
parent ba9d5201cf
commit c20e679f2c
13 changed files with 1904 additions and 6865 deletions

View File

@ -11,3 +11,4 @@ addons:
sauce_connect: true
before_script:
- npm install -g grunt-cli
- npm install -g uglify-js

View File

@ -1,5 +1,5 @@
/*global module:false*/
var _ = require('lodash');
var _ = require('lodash'), path = require('path');
module.exports = function(grunt) {
@ -78,6 +78,16 @@ module.exports = function(grunt) {
}
}
},
execute: {
fabric: {
options: {
args: ['modules=' + ['text','serialization',
'parser', 'gradient', 'pattern', 'shadow', 'freedrawing',
'image_filters', 'serialization'].join(","), 'no-es5-compat', 'dest=' + path.resolve(__dirname, 'src/fabric/dist/') + '/']
},
src: ['src/fabric/build.js']
}
},
uglify: {
dist: {
src: ['<%= concat.dist.dest %>'],
@ -92,7 +102,7 @@ module.exports = function(grunt) {
}
},
watch: {
files: 'src/**/*',
files: ['src/**/*', '!src/fabric/**/*'],
tasks: ['jshint', 'build']
},
jshint: {
@ -150,17 +160,16 @@ module.exports = function(grunt) {
selenium.tests(browsers, test).onValue(done);
});
// Load tasks
grunt.loadNpmTasks('grunt-contrib-watch');
grunt.loadNpmTasks('grunt-contrib-concat');
grunt.loadNpmTasks('grunt-contrib-uglify');
grunt.loadNpmTasks('grunt-contrib-jshint');
grunt.loadNpmTasks('grunt-contrib-qunit');
grunt.loadNpmTasks('grunt-contrib-connect');
grunt.loadNpmTasks('grunt-execute');
// Default task.
grunt.registerTask('server', ['connect:cors', 'connect']);
grunt.registerTask('build', ['concat', 'uglify']);
grunt.registerTask('build', ['execute', 'concat', 'uglify']);
grunt.registerTask('default', ['jshint', 'concat', 'qunit', 'uglify']);
grunt.registerTask('travis', ['jshint', 'concat','qunit', 'uglify', 'connect:ci', 'connect:cors', 'webdriver']);

31
dist/html2canvas.js vendored
View File

@ -52,6 +52,7 @@ window.html2canvas = function(nodeList, options) {
var node = ((nodeList === undefined) ? [document.documentElement] : ((nodeList.length) ? nodeList : [nodeList]))[0];
node.setAttribute(html2canvasNodeAttribute, "true");
return renderDocument(node.ownerDocument, options, window.innerWidth, window.innerHeight).then(function(canvas) {
if (typeof(options.onrendered) === "function") {
log("options.onrendered is deprecated, html2canvas returns a Promise containing the canvas");
@ -323,7 +324,7 @@ ImageLoader.prototype.loadImage = function(imageData) {
var src = imageData.args[0];
if (src.match(/data:image\/.*;base64,/i)) {
return new ImageContainer(src.replace(/url\(['"]{0,}|['"]{0,}\)$/ig, ''), false);
} else if (/(.+).svg$/i.test(src)) {
} else if (/(.+).svg$/i.test(src) && !this.support.svg) {
return new SVGContainer(src);
} else if (this.isSameOrigin(src) || this.options.allowTaint === true) {
return new ImageContainer(src, false);
@ -1696,6 +1697,7 @@ StackingContext.prototype.getParentStack = function(context) {
function Support(document) {
this.rangeBounds = this.testRangeBounds(document);
this.cors = this.testCORS();
this.svg = this.testSVG();
}
Support.prototype.testRangeBounds = function(document) {
@ -1727,12 +1729,31 @@ Support.prototype.testCORS = function() {
return typeof((new Image()).crossOrigin) !== "undefined";
};
Support.prototype.testSVG = function() {
var img = new Image();
var canvas = document.createElement("canvas");
var ctx = canvas.getContext("2d");
img.src = "data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg'></svg>";
try {
ctx.drawImage(img, 0, 0);
canvas.toDataURL();
} catch(e) {
return false;
}
return true;
};
function SVGContainer(src) {
this.src = src;
this.image = null;
var self = this;
this.promise = XHR(src).then(function(svg) {
return new Promise(function(resolve) {
return new Promise(function(resolve, reject) {
if (!html2canvas.fabric) {
return reject(new Error("html2canvas.svg.js is not loaded, cannot render svg"));
}
html2canvas.fabric.loadSVGFromString(svg, function (objects, options) {
var canvas = new html2canvas.fabric.StaticCanvas('c');
self.image = canvas.lowerCanvasEl;
@ -1791,14 +1812,14 @@ function XHR(url) {
xhr.onload = function() {
if (xhr.status === 200) {
resolve(xhr.response);
resolve(xhr.responseText);
} else {
reject(Error(xhr.statusText));
reject(new Error(xhr.statusText));
}
};
xhr.onerror = function() {
reject(Error("Network Error"));
reject(new Error("Network Error"));
};
xhr.send();

File diff suppressed because one or more lines are too long

8665
dist/html2canvas.svg.js vendored

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

View File

@ -29,6 +29,7 @@
"grunt-contrib-qunit": "*",
"grunt-contrib-uglify": "*",
"grunt-contrib-watch": "~0.5.1",
"grunt-execute": "^0.2.2",
"lodash": "^2.4.1",
"png-js": ">= 0.1.1",
"wd": "^0.2.21"

@ -1 +0,0 @@
Subproject commit 791c74a82ef0d838fd0bd81bf942f8630a9a4a8f

View File

@ -34,7 +34,7 @@ ImageLoader.prototype.loadImage = function(imageData) {
var src = imageData.args[0];
if (src.match(/data:image\/.*;base64,/i)) {
return new ImageContainer(src.replace(/url\(['"]{0,}|['"]{0,}\)$/ig, ''), false);
} else if (/(.+).svg$/i.test(src)) {
} else if (/(.+).svg$/i.test(src) && !this.support.svg) {
return new SVGContainer(src);
} else if (this.isSameOrigin(src) || this.options.allowTaint === true) {
return new ImageContainer(src, false);

View File

@ -1,6 +1,7 @@
function Support(document) {
this.rangeBounds = this.testRangeBounds(document);
this.cors = this.testCORS();
this.svg = this.testSVG();
}
Support.prototype.testRangeBounds = function(document) {
@ -31,3 +32,18 @@ Support.prototype.testRangeBounds = function(document) {
Support.prototype.testCORS = function() {
return typeof((new Image()).crossOrigin) !== "undefined";
};
Support.prototype.testSVG = function() {
var img = new Image();
var canvas = document.createElement("canvas");
var ctx = canvas.getContext("2d");
img.src = "data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg'></svg>";
try {
ctx.drawImage(img, 0, 0);
canvas.toDataURL();
} catch(e) {
return false;
}
return true;
};

View File

@ -3,7 +3,11 @@ function SVGContainer(src) {
this.image = null;
var self = this;
this.promise = XHR(src).then(function(svg) {
return new Promise(function(resolve) {
return new Promise(function(resolve, reject) {
if (!html2canvas.fabric) {
return reject(new Error("html2canvas.svg.js is not loaded, cannot render svg"));
}
html2canvas.fabric.loadSVGFromString(svg, function (objects, options) {
var canvas = new html2canvas.fabric.StaticCanvas('c');
self.image = canvas.lowerCanvasEl;

View File

@ -5,14 +5,14 @@ function XHR(url) {
xhr.onload = function() {
if (xhr.status === 200) {
resolve(xhr.response);
resolve(xhr.responseText);
} else {
reject(Error(xhr.statusText));
reject(new Error(xhr.statusText));
}
};
xhr.onerror = function() {
reject(Error("Network Error"));
reject(new Error("Network Error"));
};
xhr.send();

View File

@ -3,10 +3,10 @@
<head>
<title>Image tests</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<script type="text/javascript" src="../../test.js"></script>
<script type="text/javascript" src="../../../test.js"></script>
</head>
<body>
SVG taints image:<br /> <!-- http://fi.wikipedia.org/wiki/Tiedosto:Svg.svg -->
<img src="../../assets/image.svg" />
<img src="../../../assets/image.svg" />
</body>
</html>