mirror of
https://github.com/niklasvh/html2canvas.git
synced 2023-08-10 21:13:10 +03:00
Switched build process to use grunt
This commit is contained in:
parent
6675a219f3
commit
c5d82acdf6
61
grunt.js
Normal file
61
grunt.js
Normal file
@ -0,0 +1,61 @@
|
|||||||
|
/*global module:false*/
|
||||||
|
module.exports = function(grunt) {
|
||||||
|
|
||||||
|
// Project configuration.
|
||||||
|
grunt.initConfig({
|
||||||
|
pkg: '<json:package.json>',
|
||||||
|
meta: {
|
||||||
|
banner: '/*\n <%= pkg.title || pkg.name %> <%= pkg.version %>' +
|
||||||
|
'<%= pkg.homepage ? " <" + pkg.homepage + ">\n" : "" %>' +
|
||||||
|
' Copyright (c) <%= grunt.template.today("yyyy") %> <%= pkg.author.name %>' +
|
||||||
|
'\n\n Released under <%= _.pluck(pkg.licenses, "type").join(", ") %> License\n*/',
|
||||||
|
pre: '(function(window, document, undefined){',
|
||||||
|
post: '})(window,document);'
|
||||||
|
},
|
||||||
|
lint: {
|
||||||
|
files: ['grunt.js', 'build/<%= pkg.name %>.js']
|
||||||
|
},
|
||||||
|
qunit: {
|
||||||
|
files: ['tests/qunit/index.html']
|
||||||
|
},
|
||||||
|
concat: {
|
||||||
|
dist: {
|
||||||
|
src: ['<banner:meta.banner>', '<banner:meta.pre>','src/*.js', 'src/renderers/Canvas.js', '<banner:meta.post>'],
|
||||||
|
dest: 'build/<%= pkg.name %>.js'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
min: {
|
||||||
|
dist: {
|
||||||
|
src: ['<banner:meta.banner>', '<config:concat.dist.dest>'],
|
||||||
|
dest: 'build/<%= pkg.name %>.min.js'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
watch: {
|
||||||
|
files: '<config:lint.files>',
|
||||||
|
tasks: 'lint qunit'
|
||||||
|
},
|
||||||
|
jshint: {
|
||||||
|
options: {
|
||||||
|
curly: true,
|
||||||
|
eqeqeq: true,
|
||||||
|
immed: true,
|
||||||
|
latedef: true,
|
||||||
|
newcap: true,
|
||||||
|
noarg: true,
|
||||||
|
sub: true,
|
||||||
|
undef: true,
|
||||||
|
boss: true,
|
||||||
|
eqnull: true,
|
||||||
|
browser: true
|
||||||
|
},
|
||||||
|
globals: {
|
||||||
|
jQuery: true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
uglify: {}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Default task.
|
||||||
|
grunt.registerTask('default', 'concat lint qunit min');
|
||||||
|
|
||||||
|
};
|
12
package.json
Normal file
12
package.json
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
{
|
||||||
|
"title": "html2canvas",
|
||||||
|
"name": "html2canvas",
|
||||||
|
"description": "File archive management library in JavaScript",
|
||||||
|
"version": "0.4.0",
|
||||||
|
"author": {
|
||||||
|
"name":"Niklas von Hertzen (@niklasvh)"
|
||||||
|
},
|
||||||
|
"homepage": "http://html2canvas.hertzen.com",
|
||||||
|
"licenses": [{"type": "MIT"}]
|
||||||
|
|
||||||
|
}
|
@ -1,10 +1,3 @@
|
|||||||
/*
|
|
||||||
html2canvas @VERSION@ <http://html2canvas.hertzen.com>
|
|
||||||
Copyright (c) 2011 Niklas von Hertzen. All rights reserved.
|
|
||||||
http://www.twitter.com/niklasvh
|
|
||||||
|
|
||||||
Released under MIT License
|
|
||||||
*/
|
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
var _html2canvas = {},
|
var _html2canvas = {},
|
||||||
|
756
src/Generate.js
756
src/Generate.js
@ -1,332 +1,326 @@
|
|||||||
/*
|
|
||||||
html2canvas @VERSION@ <http://html2canvas.hertzen.com>
|
|
||||||
Copyright (c) 2011 Niklas von Hertzen. All rights reserved.
|
|
||||||
http://www.twitter.com/niklasvh
|
|
||||||
|
|
||||||
Contributor(s):
|
|
||||||
Niklas von Hertzen <http://www.twitter.com/niklasvh>
|
|
||||||
André Fiedler <http://www.twitter.com/sonnenkiste>
|
|
||||||
|
|
||||||
Released under MIT License
|
|
||||||
*/
|
|
||||||
|
|
||||||
(function(){
|
(function(){
|
||||||
|
|
||||||
_html2canvas.Generate = {};
|
_html2canvas.Generate = {};
|
||||||
|
|
||||||
var reGradients = [
|
var reGradients = [
|
||||||
/^(-webkit-linear-gradient)\(([a-z\s]+)([\w\d\.\s,%\(\)]+)\)$/,
|
/^(-webkit-linear-gradient)\(([a-z\s]+)([\w\d\.\s,%\(\)]+)\)$/,
|
||||||
/^(-o-linear-gradient)\(([a-z\s]+)([\w\d\.\s,%\(\)]+)\)$/,
|
/^(-o-linear-gradient)\(([a-z\s]+)([\w\d\.\s,%\(\)]+)\)$/,
|
||||||
/^(-webkit-gradient)\((linear|radial),\s((?:\d{1,3}%?)\s(?:\d{1,3}%?),\s(?:\d{1,3}%?)\s(?:\d{1,3}%?))([\w\d\.\s,%\(\)-]+)\)$/,
|
/^(-webkit-gradient)\((linear|radial),\s((?:\d{1,3}%?)\s(?:\d{1,3}%?),\s(?:\d{1,3}%?)\s(?:\d{1,3}%?))([\w\d\.\s,%\(\)\-]+)\)$/,
|
||||||
/^(-moz-linear-gradient)\(((?:\d{1,3}%?)\s(?:\d{1,3}%?))([\w\d\.\s,%\(\)]+)\)$/,
|
/^(-moz-linear-gradient)\(((?:\d{1,3}%?)\s(?:\d{1,3}%?))([\w\d\.\s,%\(\)]+)\)$/,
|
||||||
/^(-webkit-radial-gradient)\(((?:\d{1,3}%?)\s(?:\d{1,3}%?)),\s(\w+)\s([a-z-]+)([\w\d\.\s,%\(\)]+)\)$/,
|
/^(-webkit-radial-gradient)\(((?:\d{1,3}%?)\s(?:\d{1,3}%?)),\s(\w+)\s([a-z\-]+)([\w\d\.\s,%\(\)]+)\)$/,
|
||||||
/^(-moz-radial-gradient)\(((?:\d{1,3}%?)\s(?:\d{1,3}%?)),\s(\w+)\s?([a-z-]*)([\w\d\.\s,%\(\)]+)\)$/,
|
/^(-moz-radial-gradient)\(((?:\d{1,3}%?)\s(?:\d{1,3}%?)),\s(\w+)\s?([a-z\-]*)([\w\d\.\s,%\(\)]+)\)$/,
|
||||||
/^(-o-radial-gradient)\(((?:\d{1,3}%?)\s(?:\d{1,3}%?)),\s(\w+)\s([a-z-]+)([\w\d\.\s,%\(\)]+)\)$/
|
/^(-o-radial-gradient)\(((?:\d{1,3}%?)\s(?:\d{1,3}%?)),\s(\w+)\s([a-z\-]+)([\w\d\.\s,%\(\)]+)\)$/
|
||||||
];
|
];
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* TODO: Add IE10 vendor prefix (-ms) support
|
* TODO: Add IE10 vendor prefix (-ms) support
|
||||||
* TODO: Add W3C gradient (linear-gradient) support
|
* TODO: Add W3C gradient (linear-gradient) support
|
||||||
* TODO: Add old Webkit -webkit-gradient(radial, ...) support
|
* TODO: Add old Webkit -webkit-gradient(radial, ...) support
|
||||||
* TODO: Maybe some RegExp optimizations are possible ;o)
|
* TODO: Maybe some RegExp optimizations are possible ;o)
|
||||||
*/
|
*/
|
||||||
_html2canvas.Generate.parseGradient = function(css, bounds) {
|
_html2canvas.Generate.parseGradient = function(css, bounds) {
|
||||||
var gradient, i, len = reGradients.length, m1, stop, m2, m2Len, step, m3;
|
var gradient, i, len = reGradients.length, m1, stop, m2, m2Len, step, m3, tl,tr,br,bl;
|
||||||
|
|
||||||
for(i = 0; i < len; i+=1){
|
for(i = 0; i < len; i+=1){
|
||||||
m1 = css.match(reGradients[i]);
|
m1 = css.match(reGradients[i]);
|
||||||
if(m1) break;
|
if(m1) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(m1) {
|
if(m1) {
|
||||||
switch(m1[1]) {
|
switch(m1[1]) {
|
||||||
case '-webkit-linear-gradient':
|
case '-webkit-linear-gradient':
|
||||||
case '-o-linear-gradient':
|
case '-o-linear-gradient':
|
||||||
|
|
||||||
gradient = {
|
gradient = {
|
||||||
type: 'linear',
|
type: 'linear',
|
||||||
x0: null,
|
x0: null,
|
||||||
y0: null,
|
y0: null,
|
||||||
x1: null,
|
x1: null,
|
||||||
y1: null,
|
y1: null,
|
||||||
colorStops: []
|
colorStops: []
|
||||||
};
|
};
|
||||||
|
|
||||||
// get coordinates
|
// get coordinates
|
||||||
m2 = m1[2].match(/\w+/g);
|
m2 = m1[2].match(/\w+/g);
|
||||||
if(m2){
|
if(m2){
|
||||||
m2Len = m2.length;
|
m2Len = m2.length;
|
||||||
for(i = 0; i < m2Len; i+=1){
|
for(i = 0; i < m2Len; i+=1){
|
||||||
switch(m2[i]) {
|
switch(m2[i]) {
|
||||||
case 'top':
|
case 'top':
|
||||||
gradient.y0 = 0;
|
gradient.y0 = 0;
|
||||||
gradient.y1 = bounds.height;
|
gradient.y1 = bounds.height;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'right':
|
case 'right':
|
||||||
gradient.x0 = bounds.width;
|
gradient.x0 = bounds.width;
|
||||||
gradient.x1 = 0;
|
gradient.x1 = 0;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'bottom':
|
case 'bottom':
|
||||||
gradient.y0 = bounds.height;
|
gradient.y0 = bounds.height;
|
||||||
gradient.y1 = 0;
|
gradient.y1 = 0;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'left':
|
case 'left':
|
||||||
gradient.x0 = 0;
|
gradient.x0 = 0;
|
||||||
gradient.x1 = bounds.width;
|
gradient.x1 = bounds.width;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(gradient.x0 === null && gradient.x1 === null){ // center
|
if(gradient.x0 === null && gradient.x1 === null){ // center
|
||||||
gradient.x0 = gradient.x1 = bounds.width / 2;
|
gradient.x0 = gradient.x1 = bounds.width / 2;
|
||||||
}
|
}
|
||||||
if(gradient.y0 === null && gradient.y1 === null){ // center
|
if(gradient.y0 === null && gradient.y1 === null){ // center
|
||||||
gradient.y0 = gradient.y1 = bounds.height / 2;
|
gradient.y0 = gradient.y1 = bounds.height / 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
// get colors and stops
|
||||||
|
m2 = m1[3].match(/((?:rgb|rgba)\(\d{1,3},\s\d{1,3},\s\d{1,3}(?:,\s[0-9\.]+)?\)(?:\s\d{1,3}(?:%|px))?)+/g);
|
||||||
|
if(m2){
|
||||||
|
m2Len = m2.length;
|
||||||
|
step = 1 / Math.max(m2Len - 1, 1);
|
||||||
|
for(i = 0; i < m2Len; i+=1){
|
||||||
|
m3 = m2[i].match(/((?:rgb|rgba)\(\d{1,3},\s\d{1,3},\s\d{1,3}(?:,\s[0-9\.]+)?\))\s*(\d{1,3})?(%|px)?/);
|
||||||
|
if(m3[2]){
|
||||||
|
stop = parseFloat(m3[2]);
|
||||||
|
if(m3[3] === '%'){
|
||||||
|
stop /= 100;
|
||||||
|
} else { // px - stupid opera
|
||||||
|
stop /= bounds.width;
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
stop = i * step;
|
||||||
|
}
|
||||||
|
gradient.colorStops.push({
|
||||||
|
color: m3[1],
|
||||||
|
stop: stop
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
// get colors and stops
|
case '-webkit-gradient':
|
||||||
m2 = m1[3].match(/((?:rgb|rgba)\(\d{1,3},\s\d{1,3},\s\d{1,3}(?:,\s[0-9\.]+)?\)(?:\s\d{1,3}(?:%|px))?)+/g);
|
|
||||||
if(m2){
|
gradient = {
|
||||||
m2Len = m2.length;
|
type: m1[2] === 'radial' ? 'circle' : m1[2], // TODO: Add radial gradient support for older mozilla definitions
|
||||||
step = 1 / Math.max(m2Len - 1, 1);
|
x0: 0,
|
||||||
for(i = 0; i < m2Len; i+=1){
|
y0: 0,
|
||||||
m3 = m2[i].match(/((?:rgb|rgba)\(\d{1,3},\s\d{1,3},\s\d{1,3}(?:,\s[0-9\.]+)?\))\s*(\d{1,3})?(%|px)?/);
|
x1: 0,
|
||||||
if(m3[2]){
|
y1: 0,
|
||||||
stop = parseFloat(m3[2]);
|
colorStops: []
|
||||||
if(m3[3] === '%'){
|
};
|
||||||
stop /= 100;
|
|
||||||
} else { // px - stupid opera
|
// get coordinates
|
||||||
stop /= bounds.width;
|
m2 = m1[3].match(/(\d{1,3})%?\s(\d{1,3})%?,\s(\d{1,3})%?\s(\d{1,3})%?/);
|
||||||
}
|
if(m2){
|
||||||
} else {
|
gradient.x0 = (m2[1] * bounds.width) / 100;
|
||||||
stop = i * step;
|
gradient.y0 = (m2[2] * bounds.height) / 100;
|
||||||
}
|
gradient.x1 = (m2[3] * bounds.width) / 100;
|
||||||
gradient.colorStops.push({
|
gradient.y1 = (m2[4] * bounds.height) / 100;
|
||||||
color: m3[1],
|
}
|
||||||
stop: stop
|
|
||||||
});
|
// get colors and stops
|
||||||
}
|
m2 = m1[4].match(/((?:from|to|color-stop)\((?:[0-9\.]+,\s)?(?:rgb|rgba)\(\d{1,3},\s\d{1,3},\s\d{1,3}(?:,\s[0-9\.]+)?\)\))+/g);
|
||||||
|
if(m2){
|
||||||
|
m2Len = m2.length;
|
||||||
|
for(i = 0; i < m2Len; i+=1){
|
||||||
|
m3 = m2[i].match(/(from|to|color-stop)\(([0-9\.]+)?(?:,\s)?((?:rgb|rgba)\(\d{1,3},\s\d{1,3},\s\d{1,3}(?:,\s[0-9\.]+)?\))\)/);
|
||||||
|
stop = parseFloat(m3[2]);
|
||||||
|
if(m3[1] === 'from') {
|
||||||
|
stop = 0.0;
|
||||||
|
}
|
||||||
|
if(m3[1] === 'to') {
|
||||||
|
stop = 1.0;
|
||||||
|
}
|
||||||
|
gradient.colorStops.push({
|
||||||
|
color: m3[3],
|
||||||
|
stop: stop
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case '-moz-linear-gradient':
|
||||||
|
|
||||||
|
gradient = {
|
||||||
|
type: 'linear',
|
||||||
|
x0: 0,
|
||||||
|
y0: 0,
|
||||||
|
x1: 0,
|
||||||
|
y1: 0,
|
||||||
|
colorStops: []
|
||||||
|
};
|
||||||
|
|
||||||
|
// get coordinates
|
||||||
|
m2 = m1[2].match(/(\d{1,3})%?\s(\d{1,3})%?/);
|
||||||
|
|
||||||
|
// m2[1] == 0% -> left
|
||||||
|
// m2[1] == 50% -> center
|
||||||
|
// m2[1] == 100% -> right
|
||||||
|
|
||||||
|
// m2[2] == 0% -> top
|
||||||
|
// m2[2] == 50% -> center
|
||||||
|
// m2[2] == 100% -> bottom
|
||||||
|
|
||||||
|
if(m2){
|
||||||
|
gradient.x0 = (m2[1] * bounds.width) / 100;
|
||||||
|
gradient.y0 = (m2[2] * bounds.height) / 100;
|
||||||
|
gradient.x1 = bounds.width - gradient.x0;
|
||||||
|
gradient.y1 = bounds.height - gradient.y0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// get colors and stops
|
||||||
|
m2 = m1[3].match(/((?:rgb|rgba)\(\d{1,3},\s\d{1,3},\s\d{1,3}(?:,\s[0-9\.]+)?\)(?:\s\d{1,3}%)?)+/g);
|
||||||
|
if(m2){
|
||||||
|
m2Len = m2.length;
|
||||||
|
step = 1 / Math.max(m2Len - 1, 1);
|
||||||
|
for(i = 0; i < m2Len; i+=1){
|
||||||
|
m3 = m2[i].match(/((?:rgb|rgba)\(\d{1,3},\s\d{1,3},\s\d{1,3}(?:,\s[0-9\.]+)?\))\s*(\d{1,3})?(%)?/);
|
||||||
|
if(m3[2]){
|
||||||
|
stop = parseFloat(m3[2]);
|
||||||
|
if(m3[3]){ // percentage
|
||||||
|
stop /= 100;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
stop = i * step;
|
||||||
|
}
|
||||||
|
gradient.colorStops.push({
|
||||||
|
color: m3[1],
|
||||||
|
stop: stop
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case '-webkit-radial-gradient':
|
||||||
|
case '-moz-radial-gradient':
|
||||||
|
case '-o-radial-gradient':
|
||||||
|
|
||||||
|
gradient = {
|
||||||
|
type: 'circle',
|
||||||
|
x0: 0,
|
||||||
|
y0: 0,
|
||||||
|
x1: bounds.width,
|
||||||
|
y1: bounds.height,
|
||||||
|
cx: 0,
|
||||||
|
cy: 0,
|
||||||
|
rx: 0,
|
||||||
|
ry: 0,
|
||||||
|
colorStops: []
|
||||||
|
};
|
||||||
|
|
||||||
|
// center
|
||||||
|
m2 = m1[2].match(/(\d{1,3})%?\s(\d{1,3})%?/);
|
||||||
|
if(m2){
|
||||||
|
gradient.cx = (m2[1] * bounds.width) / 100;
|
||||||
|
gradient.cy = (m2[2] * bounds.height) / 100;
|
||||||
|
}
|
||||||
|
|
||||||
|
// size
|
||||||
|
m2 = m1[3].match(/\w+/);
|
||||||
|
m3 = m1[4].match(/[a-z\-]*/);
|
||||||
|
if(m2 && m3){
|
||||||
|
switch(m3[0]){
|
||||||
|
case 'farthest-corner':
|
||||||
|
case 'cover': // is equivalent to farthest-corner
|
||||||
|
case '': // mozilla removes "cover" from definition :(
|
||||||
|
tl = Math.sqrt(Math.pow(gradient.cx, 2) + Math.pow(gradient.cy, 2));
|
||||||
|
tr = Math.sqrt(Math.pow(gradient.cx, 2) + Math.pow(gradient.y1 - gradient.cy, 2));
|
||||||
|
br = Math.sqrt(Math.pow(gradient.x1 - gradient.cx, 2) + Math.pow(gradient.y1 - gradient.cy, 2));
|
||||||
|
bl = Math.sqrt(Math.pow(gradient.x1 - gradient.cx, 2) + Math.pow(gradient.cy, 2));
|
||||||
|
gradient.rx = gradient.ry = Math.max(tl, tr, br, bl);
|
||||||
|
break;
|
||||||
|
case 'closest-corner':
|
||||||
|
tl = Math.sqrt(Math.pow(gradient.cx, 2) + Math.pow(gradient.cy, 2));
|
||||||
|
tr = Math.sqrt(Math.pow(gradient.cx, 2) + Math.pow(gradient.y1 - gradient.cy, 2));
|
||||||
|
br = Math.sqrt(Math.pow(gradient.x1 - gradient.cx, 2) + Math.pow(gradient.y1 - gradient.cy, 2));
|
||||||
|
bl = Math.sqrt(Math.pow(gradient.x1 - gradient.cx, 2) + Math.pow(gradient.cy, 2));
|
||||||
|
gradient.rx = gradient.ry = Math.min(tl, tr, br, bl);
|
||||||
|
break;
|
||||||
|
case 'farthest-side':
|
||||||
|
if(m2[0] === 'circle'){
|
||||||
|
gradient.rx = gradient.ry = Math.max(
|
||||||
|
gradient.cx,
|
||||||
|
gradient.cy,
|
||||||
|
gradient.x1 - gradient.cx,
|
||||||
|
gradient.y1 - gradient.cy
|
||||||
|
);
|
||||||
|
} else { // ellipse
|
||||||
|
|
||||||
|
gradient.type = m2[0];
|
||||||
|
|
||||||
|
gradient.rx = Math.max(
|
||||||
|
gradient.cx,
|
||||||
|
gradient.x1 - gradient.cx
|
||||||
|
);
|
||||||
|
gradient.ry = Math.max(
|
||||||
|
gradient.cy,
|
||||||
|
gradient.y1 - gradient.cy
|
||||||
|
);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 'closest-side':
|
||||||
|
case 'contain': // is equivalent to closest-side
|
||||||
|
if(m2[0] === 'circle'){
|
||||||
|
gradient.rx = gradient.ry = Math.min(
|
||||||
|
gradient.cx,
|
||||||
|
gradient.cy,
|
||||||
|
gradient.x1 - gradient.cx,
|
||||||
|
gradient.y1 - gradient.cy
|
||||||
|
);
|
||||||
|
} else { // ellipse
|
||||||
|
|
||||||
|
gradient.type = m2[0];
|
||||||
|
|
||||||
|
gradient.rx = Math.min(
|
||||||
|
gradient.cx,
|
||||||
|
gradient.x1 - gradient.cx
|
||||||
|
);
|
||||||
|
gradient.ry = Math.min(
|
||||||
|
gradient.cy,
|
||||||
|
gradient.y1 - gradient.cy
|
||||||
|
);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case '-webkit-gradient':
|
// TODO: add support for "30px 40px" sizes (webkit only)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
gradient = {
|
// color stops
|
||||||
type: m1[2] === 'radial' ? 'circle' : m1[2], // TODO: Add radial gradient support for older mozilla definitions
|
m2 = m1[5].match(/((?:rgb|rgba)\(\d{1,3},\s\d{1,3},\s\d{1,3}(?:,\s[0-9\.]+)?\)(?:\s\d{1,3}(?:%|px))?)+/g);
|
||||||
x0: 0,
|
if(m2){
|
||||||
y0: 0,
|
m2Len = m2.length;
|
||||||
x1: 0,
|
step = 1 / Math.max(m2Len - 1, 1);
|
||||||
y1: 0,
|
for(i = 0; i < m2Len; i+=1){
|
||||||
colorStops: []
|
m3 = m2[i].match(/((?:rgb|rgba)\(\d{1,3},\s\d{1,3},\s\d{1,3}(?:,\s[0-9\.]+)?\))\s*(\d{1,3})?(%|px)?/);
|
||||||
};
|
if(m3[2]){
|
||||||
|
stop = parseFloat(m3[2]);
|
||||||
// get coordinates
|
if(m3[3] === '%'){
|
||||||
m2 = m1[3].match(/(\d{1,3})%?\s(\d{1,3})%?,\s(\d{1,3})%?\s(\d{1,3})%?/);
|
stop /= 100;
|
||||||
if(m2){
|
} else { // px - stupid opera
|
||||||
gradient.x0 = (m2[1] * bounds.width) / 100;
|
stop /= bounds.width;
|
||||||
gradient.y0 = (m2[2] * bounds.height) / 100;
|
|
||||||
gradient.x1 = (m2[3] * bounds.width) / 100;
|
|
||||||
gradient.y1 = (m2[4] * bounds.height) / 100;
|
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
// get colors and stops
|
stop = i * step;
|
||||||
m2 = m1[4].match(/((?:from|to|color-stop)\((?:[0-9\.]+,\s)?(?:rgb|rgba)\(\d{1,3},\s\d{1,3},\s\d{1,3}(?:,\s[0-9\.]+)?\)\))+/g);
|
}
|
||||||
if(m2){
|
gradient.colorStops.push({
|
||||||
m2Len = m2.length;
|
color: m3[1],
|
||||||
for(i = 0; i < m2Len; i+=1){
|
stop: stop
|
||||||
m3 = m2[i].match(/(from|to|color-stop)\(([0-9\.]+)?(?:,\s)?((?:rgb|rgba)\(\d{1,3},\s\d{1,3},\s\d{1,3}(?:,\s[0-9\.]+)?\))\)/);
|
});
|
||||||
stop = parseFloat(m3[2]);
|
}
|
||||||
if(m3[1] === 'from') stop = 0.0;
|
}
|
||||||
if(m3[1] === 'to') stop = 1.0;
|
break;
|
||||||
gradient.colorStops.push({
|
}
|
||||||
color: m3[3],
|
|
||||||
stop: stop
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case '-moz-linear-gradient':
|
|
||||||
|
|
||||||
gradient = {
|
|
||||||
type: 'linear',
|
|
||||||
x0: 0,
|
|
||||||
y0: 0,
|
|
||||||
x1: 0,
|
|
||||||
y1: 0,
|
|
||||||
colorStops: []
|
|
||||||
};
|
|
||||||
|
|
||||||
// get coordinates
|
|
||||||
m2 = m1[2].match(/(\d{1,3})%?\s(\d{1,3})%?/);
|
|
||||||
|
|
||||||
// m2[1] == 0% -> left
|
|
||||||
// m2[1] == 50% -> center
|
|
||||||
// m2[1] == 100% -> right
|
|
||||||
|
|
||||||
// m2[2] == 0% -> top
|
|
||||||
// m2[2] == 50% -> center
|
|
||||||
// m2[2] == 100% -> bottom
|
|
||||||
|
|
||||||
if(m2){
|
|
||||||
gradient.x0 = (m2[1] * bounds.width) / 100;
|
|
||||||
gradient.y0 = (m2[2] * bounds.height) / 100;
|
|
||||||
gradient.x1 = bounds.width - gradient.x0;
|
|
||||||
gradient.y1 = bounds.height - gradient.y0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// get colors and stops
|
|
||||||
m2 = m1[3].match(/((?:rgb|rgba)\(\d{1,3},\s\d{1,3},\s\d{1,3}(?:,\s[0-9\.]+)?\)(?:\s\d{1,3}%)?)+/g);
|
|
||||||
if(m2){
|
|
||||||
m2Len = m2.length;
|
|
||||||
step = 1 / Math.max(m2Len - 1, 1);
|
|
||||||
for(i = 0; i < m2Len; i+=1){
|
|
||||||
m3 = m2[i].match(/((?:rgb|rgba)\(\d{1,3},\s\d{1,3},\s\d{1,3}(?:,\s[0-9\.]+)?\))\s*(\d{1,3})?(%)?/);
|
|
||||||
if(m3[2]){
|
|
||||||
stop = parseFloat(m3[2]);
|
|
||||||
if(m3[3]){ // percentage
|
|
||||||
stop /= 100;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
stop = i * step;
|
|
||||||
}
|
|
||||||
gradient.colorStops.push({
|
|
||||||
color: m3[1],
|
|
||||||
stop: stop
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case '-webkit-radial-gradient':
|
|
||||||
case '-moz-radial-gradient':
|
|
||||||
case '-o-radial-gradient':
|
|
||||||
|
|
||||||
gradient = {
|
|
||||||
type: 'circle',
|
|
||||||
x0: 0,
|
|
||||||
y0: 0,
|
|
||||||
x1: bounds.width,
|
|
||||||
y1: bounds.height,
|
|
||||||
cx: 0,
|
|
||||||
cy: 0,
|
|
||||||
rx: 0,
|
|
||||||
ry: 0,
|
|
||||||
colorStops: []
|
|
||||||
};
|
|
||||||
|
|
||||||
// center
|
|
||||||
m2 = m1[2].match(/(\d{1,3})%?\s(\d{1,3})%?/);
|
|
||||||
if(m2){
|
|
||||||
gradient.cx = (m2[1] * bounds.width) / 100;
|
|
||||||
gradient.cy = (m2[2] * bounds.height) / 100;
|
|
||||||
}
|
|
||||||
|
|
||||||
// size
|
|
||||||
m2 = m1[3].match(/\w+/);
|
|
||||||
m3 = m1[4].match(/[a-z-]*/);
|
|
||||||
if(m2 && m3){
|
|
||||||
switch(m3[0]){
|
|
||||||
case 'farthest-corner':
|
|
||||||
case 'cover': // is equivalent to farthest-corner
|
|
||||||
case '': // mozilla removes "cover" from definition :(
|
|
||||||
var tl = Math.sqrt(Math.pow(gradient.cx, 2) + Math.pow(gradient.cy, 2));
|
|
||||||
var tr = Math.sqrt(Math.pow(gradient.cx, 2) + Math.pow(gradient.y1 - gradient.cy, 2));
|
|
||||||
var br = Math.sqrt(Math.pow(gradient.x1 - gradient.cx, 2) + Math.pow(gradient.y1 - gradient.cy, 2));
|
|
||||||
var bl = Math.sqrt(Math.pow(gradient.x1 - gradient.cx, 2) + Math.pow(gradient.cy, 2));
|
|
||||||
gradient.rx = gradient.ry = Math.max(tl, tr, br, bl);
|
|
||||||
break;
|
|
||||||
case 'closest-corner':
|
|
||||||
var tl = Math.sqrt(Math.pow(gradient.cx, 2) + Math.pow(gradient.cy, 2));
|
|
||||||
var tr = Math.sqrt(Math.pow(gradient.cx, 2) + Math.pow(gradient.y1 - gradient.cy, 2));
|
|
||||||
var br = Math.sqrt(Math.pow(gradient.x1 - gradient.cx, 2) + Math.pow(gradient.y1 - gradient.cy, 2));
|
|
||||||
var bl = Math.sqrt(Math.pow(gradient.x1 - gradient.cx, 2) + Math.pow(gradient.cy, 2));
|
|
||||||
gradient.rx = gradient.ry = Math.min(tl, tr, br, bl);
|
|
||||||
break;
|
|
||||||
case 'farthest-side':
|
|
||||||
if(m2[0] === 'circle'){
|
|
||||||
gradient.rx = gradient.ry = Math.max(
|
|
||||||
gradient.cx,
|
|
||||||
gradient.cy,
|
|
||||||
gradient.x1 - gradient.cx,
|
|
||||||
gradient.y1 - gradient.cy
|
|
||||||
);
|
|
||||||
} else { // ellipse
|
|
||||||
|
|
||||||
gradient.type = m2[0];
|
|
||||||
|
|
||||||
gradient.rx = Math.max(
|
|
||||||
gradient.cx,
|
|
||||||
gradient.x1 - gradient.cx
|
|
||||||
);
|
|
||||||
gradient.ry = Math.max(
|
|
||||||
gradient.cy,
|
|
||||||
gradient.y1 - gradient.cy
|
|
||||||
);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case 'closest-side':
|
|
||||||
case 'contain': // is equivalent to closest-side
|
|
||||||
if(m2[0] === 'circle'){
|
|
||||||
gradient.rx = gradient.ry = Math.min(
|
|
||||||
gradient.cx,
|
|
||||||
gradient.cy,
|
|
||||||
gradient.x1 - gradient.cx,
|
|
||||||
gradient.y1 - gradient.cy
|
|
||||||
);
|
|
||||||
} else { // ellipse
|
|
||||||
|
|
||||||
gradient.type = m2[0];
|
|
||||||
|
|
||||||
gradient.rx = Math.min(
|
|
||||||
gradient.cx,
|
|
||||||
gradient.x1 - gradient.cx
|
|
||||||
);
|
|
||||||
gradient.ry = Math.min(
|
|
||||||
gradient.cy,
|
|
||||||
gradient.y1 - gradient.cy
|
|
||||||
);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
// TODO: add support for "30px 40px" sizes (webkit only)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// color stops
|
|
||||||
m2 = m1[5].match(/((?:rgb|rgba)\(\d{1,3},\s\d{1,3},\s\d{1,3}(?:,\s[0-9\.]+)?\)(?:\s\d{1,3}(?:%|px))?)+/g);
|
|
||||||
if(m2){
|
|
||||||
m2Len = m2.length;
|
|
||||||
step = 1 / Math.max(m2Len - 1, 1);
|
|
||||||
for(i = 0; i < m2Len; i+=1){
|
|
||||||
m3 = m2[i].match(/((?:rgb|rgba)\(\d{1,3},\s\d{1,3},\s\d{1,3}(?:,\s[0-9\.]+)?\))\s*(\d{1,3})?(%|px)?/);
|
|
||||||
if(m3[2]){
|
|
||||||
stop = parseFloat(m3[2]);
|
|
||||||
if(m3[3] === '%'){
|
|
||||||
stop /= 100;
|
|
||||||
} else { // px - stupid opera
|
|
||||||
stop /= bounds.width;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
stop = i * step;
|
|
||||||
}
|
|
||||||
gradient.colorStops.push({
|
|
||||||
color: m3[1],
|
|
||||||
stop: stop
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return gradient;
|
return gradient;
|
||||||
};
|
};
|
||||||
|
|
||||||
_html2canvas.Generate.Gradient = function(src, bounds) {
|
_html2canvas.Generate.Gradient = function(src, bounds) {
|
||||||
var canvas = document.createElement('canvas'),
|
var canvas = document.createElement('canvas'),
|
||||||
ctx = canvas.getContext('2d'),
|
ctx = canvas.getContext('2d'),
|
||||||
gradient, grad, i, len, img;
|
gradient, grad, i, len, img;
|
||||||
@ -340,96 +334,96 @@ _html2canvas.Generate.Gradient = function(src, bounds) {
|
|||||||
img = new Image();
|
img = new Image();
|
||||||
|
|
||||||
if(gradient){
|
if(gradient){
|
||||||
if(gradient.type === 'linear'){
|
if(gradient.type === 'linear'){
|
||||||
grad = ctx.createLinearGradient(gradient.x0, gradient.y0, gradient.x1, gradient.y1);
|
grad = ctx.createLinearGradient(gradient.x0, gradient.y0, gradient.x1, gradient.y1);
|
||||||
|
|
||||||
for (i = 0, len = gradient.colorStops.length; i < len; i+=1) {
|
for (i = 0, len = gradient.colorStops.length; i < len; i+=1) {
|
||||||
try {
|
try {
|
||||||
grad.addColorStop(gradient.colorStops[i].stop, gradient.colorStops[i].color);
|
grad.addColorStop(gradient.colorStops[i].stop, gradient.colorStops[i].color);
|
||||||
}
|
}
|
||||||
catch(e) {
|
catch(e) {
|
||||||
h2clog(['failed to add color stop: ', e, '; tried to add: ', gradient.colorStops[i], '; stop: ', i, '; in: ', src]);
|
h2clog(['failed to add color stop: ', e, '; tried to add: ', gradient.colorStops[i], '; stop: ', i, '; in: ', src]);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
ctx.fillStyle = grad;
|
|
||||||
ctx.fillRect(0, 0, bounds.width, bounds.height);
|
|
||||||
|
|
||||||
img.src = canvas.toDataURL();
|
|
||||||
} else if(gradient.type === 'circle'){
|
|
||||||
|
|
||||||
grad = ctx.createRadialGradient(gradient.cx, gradient.cy, 0, gradient.cx, gradient.cy, gradient.rx);
|
|
||||||
|
|
||||||
for (i = 0, len = gradient.colorStops.length; i < len; i+=1) {
|
|
||||||
try {
|
|
||||||
grad.addColorStop(gradient.colorStops[i].stop, gradient.colorStops[i].color);
|
|
||||||
}
|
|
||||||
catch(e) {
|
|
||||||
h2clog(['failed to add color stop: ', e, '; tried to add: ', gradient.colorStops[i], '; stop: ', i, '; in: ', src]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ctx.fillStyle = grad;
|
|
||||||
ctx.fillRect(0, 0, bounds.width, bounds.height);
|
|
||||||
|
|
||||||
img.src = canvas.toDataURL();
|
|
||||||
} else if(gradient.type === 'ellipse'){
|
|
||||||
|
|
||||||
// draw circle
|
|
||||||
var canvasRadial = document.createElement('canvas'),
|
|
||||||
ctxRadial = canvasRadial.getContext('2d'),
|
|
||||||
ri = Math.max(gradient.rx, gradient.ry),
|
|
||||||
di = ri * 2, imgRadial;
|
|
||||||
|
|
||||||
canvasRadial.width = canvasRadial.height = di;
|
|
||||||
|
|
||||||
grad = ctxRadial.createRadialGradient(gradient.rx, gradient.ry, 0, gradient.rx, gradient.ry, ri);
|
|
||||||
|
|
||||||
for (i = 0, len = gradient.colorStops.length; i < len; i+=1) {
|
|
||||||
try {
|
|
||||||
grad.addColorStop(gradient.colorStops[i].stop, gradient.colorStops[i].color);
|
|
||||||
}
|
|
||||||
catch(e) {
|
|
||||||
h2clog(['failed to add color stop: ', e, '; tried to add: ', gradient.colorStops[i], '; stop: ', i, '; in: ', src]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ctxRadial.fillStyle = grad;
|
|
||||||
ctxRadial.fillRect(0, 0, di, di);
|
|
||||||
|
|
||||||
ctx.fillStyle = gradient.colorStops[i - 1].color;
|
|
||||||
ctx.fillRect(0, 0, canvas.width, canvas.height);
|
|
||||||
|
|
||||||
imgRadial = new Image();
|
|
||||||
imgRadial.onload = function() { // wait until the image is filled
|
|
||||||
|
|
||||||
// transform circle to ellipse
|
|
||||||
ctx.drawImage(imgRadial, gradient.cx - gradient.rx, gradient.cy - gradient.ry, 2 * gradient.rx, 2 * gradient.ry);
|
|
||||||
|
|
||||||
img.src = canvas.toDataURL();
|
|
||||||
|
|
||||||
}
|
|
||||||
imgRadial.src = canvasRadial.toDataURL();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ctx.fillStyle = grad;
|
||||||
|
ctx.fillRect(0, 0, bounds.width, bounds.height);
|
||||||
|
|
||||||
|
img.src = canvas.toDataURL();
|
||||||
|
} else if(gradient.type === 'circle'){
|
||||||
|
|
||||||
|
grad = ctx.createRadialGradient(gradient.cx, gradient.cy, 0, gradient.cx, gradient.cy, gradient.rx);
|
||||||
|
|
||||||
|
for (i = 0, len = gradient.colorStops.length; i < len; i+=1) {
|
||||||
|
try {
|
||||||
|
grad.addColorStop(gradient.colorStops[i].stop, gradient.colorStops[i].color);
|
||||||
|
}
|
||||||
|
catch(e) {
|
||||||
|
h2clog(['failed to add color stop: ', e, '; tried to add: ', gradient.colorStops[i], '; stop: ', i, '; in: ', src]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx.fillStyle = grad;
|
||||||
|
ctx.fillRect(0, 0, bounds.width, bounds.height);
|
||||||
|
|
||||||
|
img.src = canvas.toDataURL();
|
||||||
|
} else if(gradient.type === 'ellipse'){
|
||||||
|
|
||||||
|
// draw circle
|
||||||
|
var canvasRadial = document.createElement('canvas'),
|
||||||
|
ctxRadial = canvasRadial.getContext('2d'),
|
||||||
|
ri = Math.max(gradient.rx, gradient.ry),
|
||||||
|
di = ri * 2, imgRadial;
|
||||||
|
|
||||||
|
canvasRadial.width = canvasRadial.height = di;
|
||||||
|
|
||||||
|
grad = ctxRadial.createRadialGradient(gradient.rx, gradient.ry, 0, gradient.rx, gradient.ry, ri);
|
||||||
|
|
||||||
|
for (i = 0, len = gradient.colorStops.length; i < len; i+=1) {
|
||||||
|
try {
|
||||||
|
grad.addColorStop(gradient.colorStops[i].stop, gradient.colorStops[i].color);
|
||||||
|
}
|
||||||
|
catch(e) {
|
||||||
|
h2clog(['failed to add color stop: ', e, '; tried to add: ', gradient.colorStops[i], '; stop: ', i, '; in: ', src]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ctxRadial.fillStyle = grad;
|
||||||
|
ctxRadial.fillRect(0, 0, di, di);
|
||||||
|
|
||||||
|
ctx.fillStyle = gradient.colorStops[i - 1].color;
|
||||||
|
ctx.fillRect(0, 0, canvas.width, canvas.height);
|
||||||
|
|
||||||
|
imgRadial = new Image();
|
||||||
|
imgRadial.onload = function() { // wait until the image is filled
|
||||||
|
|
||||||
|
// transform circle to ellipse
|
||||||
|
ctx.drawImage(imgRadial, gradient.cx - gradient.rx, gradient.cy - gradient.ry, 2 * gradient.rx, 2 * gradient.ry);
|
||||||
|
|
||||||
|
img.src = canvas.toDataURL();
|
||||||
|
|
||||||
|
};
|
||||||
|
imgRadial.src = canvasRadial.toDataURL();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return img;
|
return img;
|
||||||
};
|
};
|
||||||
|
|
||||||
_html2canvas.Generate.ListAlpha = function(number) {
|
_html2canvas.Generate.ListAlpha = function(number) {
|
||||||
var tmp = "",
|
var tmp = "",
|
||||||
modulus;
|
modulus;
|
||||||
|
|
||||||
do {
|
do {
|
||||||
modulus = number % 26;
|
modulus = number % 26;
|
||||||
tmp = String.fromCharCode((modulus) + 64) + tmp;
|
tmp = String.fromCharCode((modulus) + 64) + tmp;
|
||||||
number = number / 26;
|
number = number / 26;
|
||||||
}while((number*26) > 26);
|
}while((number*26) > 26);
|
||||||
|
|
||||||
return tmp;
|
return tmp;
|
||||||
};
|
};
|
||||||
|
|
||||||
_html2canvas.Generate.ListRoman = function(number) {
|
_html2canvas.Generate.ListRoman = function(number) {
|
||||||
var romanArray = ["M", "CM", "D", "CD", "C", "XC", "L", "XL", "X", "IX", "V", "IV", "I"],
|
var romanArray = ["M", "CM", "D", "CD", "C", "XC", "L", "XL", "X", "IX", "V", "IV", "I"],
|
||||||
decimal = [1000, 900, 500, 400, 100, 90, 50, 40, 10, 9, 5, 4, 1],
|
decimal = [1000, 900, 500, 400, 100, 90, 50, 40, 10, 9, 5, 4, 1],
|
||||||
roman = "",
|
roman = "",
|
||||||
@ -437,18 +431,18 @@ _html2canvas.Generate.ListRoman = function(number) {
|
|||||||
len = romanArray.length;
|
len = romanArray.length;
|
||||||
|
|
||||||
if (number <= 0 || number >= 4000) {
|
if (number <= 0 || number >= 4000) {
|
||||||
return number;
|
return number;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (v=0; v < len; v+=1) {
|
for (v=0; v < len; v+=1) {
|
||||||
while (number >= decimal[v]) {
|
while (number >= decimal[v]) {
|
||||||
number -= decimal[v];
|
number -= decimal[v];
|
||||||
roman += romanArray[v];
|
roman += romanArray[v];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return roman;
|
return roman;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
})();
|
})();
|
2298
src/Parse.js
2298
src/Parse.js
File diff suppressed because it is too large
Load Diff
587
src/Preload.js
587
src/Preload.js
@ -1,360 +1,329 @@
|
|||||||
/*
|
|
||||||
html2canvas @VERSION@ <http://html2canvas.hertzen.com>
|
|
||||||
Copyright (c) 2011 Niklas von Hertzen. All rights reserved.
|
|
||||||
http://www.twitter.com/niklasvh
|
|
||||||
|
|
||||||
Released under MIT License
|
|
||||||
*/
|
|
||||||
|
|
||||||
_html2canvas.Preload = function( options ) {
|
_html2canvas.Preload = function( options ) {
|
||||||
|
|
||||||
var images = {
|
var images = {
|
||||||
numLoaded: 0, // also failed are counted here
|
numLoaded: 0, // also failed are counted here
|
||||||
numFailed: 0,
|
numFailed: 0,
|
||||||
numTotal: 0,
|
numTotal: 0,
|
||||||
cleanupDone: false
|
cleanupDone: false
|
||||||
},
|
},
|
||||||
pageOrigin,
|
pageOrigin,
|
||||||
methods,
|
methods,
|
||||||
|
i,
|
||||||
|
count = 0,
|
||||||
|
element = options.elements[0] || document.body,
|
||||||
|
doc = element.ownerDocument,
|
||||||
|
domImages = doc.images, // TODO probably should limit it to images present in the element only
|
||||||
|
imgLen = domImages.length,
|
||||||
|
link = doc.createElement("a"),
|
||||||
|
supportCORS = (function( img ){
|
||||||
|
return (img.crossOrigin !== undefined);
|
||||||
|
})(new Image()),
|
||||||
|
timeoutTimer;
|
||||||
|
|
||||||
|
link.href = window.location.href;
|
||||||
|
pageOrigin = link.protocol + link.host;
|
||||||
|
|
||||||
|
function isSameOrigin(url){
|
||||||
|
link.href = url;
|
||||||
|
link.href = link.href; // YES, BELIEVE IT OR NOT, that is required for IE9 - http://jsfiddle.net/niklasvh/2e48b/
|
||||||
|
var origin = link.protocol + link.host;
|
||||||
|
return (origin === pageOrigin);
|
||||||
|
}
|
||||||
|
|
||||||
|
function start(){
|
||||||
|
h2clog("html2canvas: start: images: " + images.numLoaded + " / " + images.numTotal + " (failed: " + images.numFailed + ")");
|
||||||
|
if (!images.firstRun && images.numLoaded >= images.numTotal){
|
||||||
|
h2clog("Finished loading images: # " + images.numTotal + " (failed: " + images.numFailed + ")");
|
||||||
|
|
||||||
|
if (typeof options.complete === "function"){
|
||||||
|
options.complete(images);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO modify proxy to serve images with CORS enabled, where available
|
||||||
|
function proxyGetImage(url, img, imageObj){
|
||||||
|
var callback_name,
|
||||||
|
scriptUrl = options.proxy,
|
||||||
|
script;
|
||||||
|
|
||||||
|
link.href = url;
|
||||||
|
url = link.href; // work around for pages with base href="" set - WARNING: this may change the url
|
||||||
|
|
||||||
|
callback_name = 'html2canvas_' + (count++);
|
||||||
|
imageObj.callbackname = callback_name;
|
||||||
|
|
||||||
|
if (scriptUrl.indexOf("?") > -1) {
|
||||||
|
scriptUrl += "&";
|
||||||
|
} else {
|
||||||
|
scriptUrl += "?";
|
||||||
|
}
|
||||||
|
scriptUrl += 'url=' + encodeURIComponent(url) + '&callback=' + callback_name;
|
||||||
|
script = doc.createElement("script");
|
||||||
|
|
||||||
|
window[callback_name] = function(a){
|
||||||
|
if (a.substring(0,6) === "error:"){
|
||||||
|
imageObj.succeeded = false;
|
||||||
|
images.numLoaded++;
|
||||||
|
images.numFailed++;
|
||||||
|
start();
|
||||||
|
} else {
|
||||||
|
setImageLoadHandlers(img, imageObj);
|
||||||
|
img.src = a;
|
||||||
|
}
|
||||||
|
window[callback_name] = undefined; // to work with IE<9 // NOTE: that the undefined callback property-name still exists on the window object (for IE<9)
|
||||||
|
try {
|
||||||
|
delete window[callback_name]; // for all browser that support this
|
||||||
|
} catch(ex) {}
|
||||||
|
script.parentNode.removeChild(script);
|
||||||
|
script = null;
|
||||||
|
delete imageObj.script;
|
||||||
|
delete imageObj.callbackname;
|
||||||
|
};
|
||||||
|
|
||||||
|
script.setAttribute("type", "text/javascript");
|
||||||
|
script.setAttribute("src", scriptUrl);
|
||||||
|
imageObj.script = script;
|
||||||
|
window.document.body.appendChild(script);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
function getImages (el) {
|
||||||
|
|
||||||
|
var contents = _html2canvas.Util.Children(el),
|
||||||
i,
|
i,
|
||||||
count = 0,
|
background_image,
|
||||||
element = options.elements[0] || document.body,
|
src,
|
||||||
doc = element.ownerDocument,
|
img,
|
||||||
domImages = doc.images, // TODO probably should limit it to images present in the element only
|
elNodeType = false;
|
||||||
imgLen = domImages.length,
|
|
||||||
link = doc.createElement("a"),
|
|
||||||
supportCORS = (function( img ){
|
|
||||||
return (img.crossOrigin !== undefined);
|
|
||||||
})(new Image()),
|
|
||||||
timeoutTimer;
|
|
||||||
|
|
||||||
link.href = window.location.href;
|
// Firefox fails with permission denied on pages with iframes
|
||||||
pageOrigin = link.protocol + link.host;
|
try {
|
||||||
|
var contentsLen = contents.length;
|
||||||
|
for (i = 0; i < contentsLen; i+=1 ){
|
||||||
|
getImages(contents[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch( e ) {}
|
||||||
|
|
||||||
|
try {
|
||||||
|
elNodeType = el.nodeType;
|
||||||
|
} catch (ex) {
|
||||||
|
elNodeType = false;
|
||||||
|
h2clog("html2canvas: failed to access some element's nodeType - Exception: " + ex.message);
|
||||||
function isSameOrigin(url){
|
|
||||||
link.href = url;
|
|
||||||
link.href = link.href; // YES, BELIEVE IT OR NOT, that is required for IE9 - http://jsfiddle.net/niklasvh/2e48b/
|
|
||||||
var origin = link.protocol + link.host;
|
|
||||||
return (origin === pageOrigin);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function start(){
|
if (elNodeType === 1 || elNodeType === undefined){
|
||||||
h2clog("html2canvas: start: images: " + images.numLoaded + " / " + images.numTotal + " (failed: " + images.numFailed + ")");
|
|
||||||
if (!images.firstRun && images.numLoaded >= images.numTotal){
|
|
||||||
h2clog("Finished loading images: # " + images.numTotal + " (failed: " + images.numFailed + ")");
|
|
||||||
|
|
||||||
if (typeof options.complete === "function"){
|
// opera throws exception on external-content.html
|
||||||
options.complete(images);
|
try {
|
||||||
}
|
background_image = _html2canvas.Util.getCSS(el, 'backgroundImage');
|
||||||
|
}catch(e) {
|
||||||
|
h2clog("html2canvas: failed to get background-image - Exception: " + e.message);
|
||||||
|
}
|
||||||
|
if ( background_image && background_image !== "1" && background_image !== "none" ) {
|
||||||
|
|
||||||
}
|
// TODO add multi image background support
|
||||||
}
|
|
||||||
|
|
||||||
// TODO modify proxy to serve images with CORS enabled, where available
|
if (/^(-webkit|-o|-moz|-ms|linear)-/.test( background_image )) {
|
||||||
function proxyGetImage(url, img, imageObj){
|
|
||||||
var callback_name,
|
|
||||||
scriptUrl = options.proxy,
|
|
||||||
script;
|
|
||||||
|
|
||||||
link.href = url;
|
img = _html2canvas.Generate.Gradient( background_image, _html2canvas.Util.Bounds( el ) );
|
||||||
url = link.href; // work around for pages with base href="" set - WARNING: this may change the url
|
|
||||||
|
|
||||||
callback_name = 'html2canvas_' + (count++);
|
if ( img !== undefined ){
|
||||||
imageObj.callbackname = callback_name;
|
images[background_image] = {
|
||||||
|
img: img,
|
||||||
|
succeeded: true
|
||||||
|
};
|
||||||
|
images.numTotal++;
|
||||||
|
images.numLoaded++;
|
||||||
|
start();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
if (scriptUrl.indexOf("?") > -1) {
|
|
||||||
scriptUrl += "&";
|
|
||||||
} else {
|
} else {
|
||||||
scriptUrl += "?";
|
src = _html2canvas.Util.backgroundImage(background_image.match(/data:image\/.*;base64,/i) ? background_image : background_image.split(",")[0]);
|
||||||
|
methods.loadImage(src);
|
||||||
}
|
}
|
||||||
scriptUrl += 'url=' + encodeURIComponent(url) + '&callback=' + callback_name;
|
|
||||||
script = doc.createElement("script");
|
|
||||||
|
|
||||||
window[callback_name] = function(a){
|
|
||||||
if (a.substring(0,6) === "error:"){
|
|
||||||
imageObj.succeeded = false;
|
|
||||||
images.numLoaded++;
|
|
||||||
images.numFailed++;
|
|
||||||
start();
|
|
||||||
} else {
|
|
||||||
setImageLoadHandlers(img, imageObj);
|
|
||||||
img.src = a;
|
|
||||||
}
|
|
||||||
window[callback_name] = undefined; // to work with IE<9 // NOTE: that the undefined callback property-name still exists on the window object (for IE<9)
|
|
||||||
try {
|
|
||||||
delete window[callback_name]; // for all browser that support this
|
|
||||||
} catch(ex) {}
|
|
||||||
script.parentNode.removeChild(script);
|
|
||||||
script = null;
|
|
||||||
delete imageObj.script;
|
|
||||||
delete imageObj.callbackname;
|
|
||||||
};
|
|
||||||
|
|
||||||
script.setAttribute("type", "text/javascript");
|
|
||||||
script.setAttribute("src", scriptUrl);
|
|
||||||
imageObj.script = script;
|
|
||||||
window.document.body.appendChild(script);
|
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function getImages (el) {
|
function setImageLoadHandlers(img, imageObj) {
|
||||||
|
img.onload = function() {
|
||||||
|
if ( imageObj.timer !== undefined ) {
|
||||||
|
// CORS succeeded
|
||||||
|
window.clearTimeout( imageObj.timer );
|
||||||
|
}
|
||||||
|
|
||||||
|
images.numLoaded++;
|
||||||
|
imageObj.succeeded = true;
|
||||||
|
img.onerror = img.onload = null;
|
||||||
|
start();
|
||||||
|
};
|
||||||
|
img.onerror = function() {
|
||||||
|
|
||||||
|
if (img.crossOrigin === "anonymous") {
|
||||||
|
// CORS failed
|
||||||
|
window.clearTimeout( imageObj.timer );
|
||||||
|
|
||||||
// if (!this.ignoreRe.test(el.nodeName)){
|
// let's try with proxy instead
|
||||||
//
|
if ( options.proxy ) {
|
||||||
|
var src = img.src;
|
||||||
var contents = _html2canvas.Util.Children(el),
|
img = new Image();
|
||||||
i,
|
imageObj.img = img;
|
||||||
background_image,
|
img.src = src;
|
||||||
src,
|
|
||||||
img,
|
|
||||||
elNodeType = false;
|
|
||||||
|
|
||||||
// Firefox fails with permission denied on pages with iframes
|
proxyGetImage( img.src, img, imageObj );
|
||||||
try {
|
return;
|
||||||
var contentsLen = contents.length;
|
|
||||||
for (i = 0; i < contentsLen; i+=1 ){
|
|
||||||
// var ignRe = new RegExp("("+this.ignoreElements+")");
|
|
||||||
// if (!ignRe.test(element.nodeName)){
|
|
||||||
getImages(contents[i]);
|
|
||||||
// }
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
catch( e ) {}
|
}
|
||||||
|
|
||||||
|
|
||||||
// }
|
images.numLoaded++;
|
||||||
try {
|
images.numFailed++;
|
||||||
elNodeType = el.nodeType;
|
imageObj.succeeded = false;
|
||||||
} catch (ex) {
|
img.onerror = img.onload = null;
|
||||||
elNodeType = false;
|
start();
|
||||||
h2clog("html2canvas: failed to access some element's nodeType - Exception: " + ex.message);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (elNodeType === 1 || elNodeType === undefined){
|
};
|
||||||
|
|
||||||
// opera throws exception on external-content.html
|
// TODO Opera has no load/error event for SVG images
|
||||||
try {
|
|
||||||
background_image = _html2canvas.Util.getCSS(el, 'backgroundImage');
|
|
||||||
}catch(e) {
|
|
||||||
h2clog("html2canvas: failed to get background-image - Exception: " + e.message);
|
|
||||||
}
|
|
||||||
if ( background_image && background_image !== "1" && background_image !== "none" ) {
|
|
||||||
|
|
||||||
// TODO add multi image background support
|
// Opera ninja onload's cached images
|
||||||
|
/*
|
||||||
if (/^(-webkit|-o|-moz|-ms|linear)-/.test( background_image )) {
|
|
||||||
|
|
||||||
img = _html2canvas.Generate.Gradient( background_image, _html2canvas.Util.Bounds( el ) );
|
|
||||||
|
|
||||||
if ( img !== undefined ){
|
|
||||||
images[background_image] = {
|
|
||||||
img: img,
|
|
||||||
succeeded: true
|
|
||||||
};
|
|
||||||
images.numTotal++;
|
|
||||||
images.numLoaded++;
|
|
||||||
start();
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
} else {
|
|
||||||
src = _html2canvas.Util.backgroundImage(background_image.match(/data:image\/.*;base64,/i) ? background_image : background_image.split(",")[0]);
|
|
||||||
methods.loadImage(src);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
if (background_image && background_image !== "1" && background_image !== "none" && background_image.substring(0,7) !== "-webkit" && background_image.substring(0,3)!== "-o-" && background_image.substring(0,4) !== "-moz"){
|
|
||||||
// TODO add multi image background support
|
|
||||||
src = _html2canvas.Util.backgroundImage(background_image.split(",")[0]);
|
|
||||||
methods.loadImage(src); */
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function setImageLoadHandlers(img, imageObj) {
|
|
||||||
img.onload = function() {
|
|
||||||
if ( imageObj.timer !== undefined ) {
|
|
||||||
// CORS succeeded
|
|
||||||
window.clearTimeout( imageObj.timer );
|
|
||||||
}
|
|
||||||
|
|
||||||
images.numLoaded++;
|
|
||||||
imageObj.succeeded = true;
|
|
||||||
img.onerror = img.onload = null;
|
|
||||||
start();
|
|
||||||
};
|
|
||||||
img.onerror = function() {
|
|
||||||
|
|
||||||
if (img.crossOrigin === "anonymous") {
|
|
||||||
// CORS failed
|
|
||||||
window.clearTimeout( imageObj.timer );
|
|
||||||
|
|
||||||
// let's try with proxy instead
|
|
||||||
if ( options.proxy ) {
|
|
||||||
var src = img.src;
|
|
||||||
img = new Image();
|
|
||||||
imageObj.img = img;
|
|
||||||
img.src = src;
|
|
||||||
|
|
||||||
proxyGetImage( img.src, img, imageObj );
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
images.numLoaded++;
|
|
||||||
images.numFailed++;
|
|
||||||
imageObj.succeeded = false;
|
|
||||||
img.onerror = img.onload = null;
|
|
||||||
start();
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
// TODO Opera has no load/error event for SVG images
|
|
||||||
|
|
||||||
// Opera ninja onload's cached images
|
|
||||||
/*
|
|
||||||
window.setTimeout(function(){
|
window.setTimeout(function(){
|
||||||
if ( img.width !== 0 && imageObj.succeeded === undefined ) {
|
if ( img.width !== 0 && imageObj.succeeded === undefined ) {
|
||||||
img.onload();
|
img.onload();
|
||||||
}
|
}
|
||||||
}, 100); // needs a reflow for base64 encoded images? interestingly timeout of 0 doesn't work but 1 does.
|
}, 100); // needs a reflow for base64 encoded images? interestingly timeout of 0 doesn't work but 1 does.
|
||||||
*/
|
*/
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
methods = {
|
methods = {
|
||||||
loadImage: function( src ) {
|
loadImage: function( src ) {
|
||||||
var img, imageObj;
|
var img, imageObj;
|
||||||
if ( src && images[src] === undefined ) {
|
if ( src && images[src] === undefined ) {
|
||||||
img = new Image();
|
img = new Image();
|
||||||
if ( src.match(/data:image\/.*;base64,/i) ) {
|
if ( src.match(/data:image\/.*;base64,/i) ) {
|
||||||
img.src = src.replace(/url\(['"]{0,}|['"]{0,}\)$/ig, '');
|
img.src = src.replace(/url\(['"]{0,}|['"]{0,}\)$/ig, '');
|
||||||
imageObj = images[src] = {
|
imageObj = images[src] = {
|
||||||
img: img
|
img: img
|
||||||
};
|
};
|
||||||
images.numTotal++;
|
images.numTotal++;
|
||||||
setImageLoadHandlers(img, imageObj);
|
setImageLoadHandlers(img, imageObj);
|
||||||
} else if ( isSameOrigin( src ) || options.allowTaint === true ) {
|
} else if ( isSameOrigin( src ) || options.allowTaint === true ) {
|
||||||
imageObj = images[src] = {
|
imageObj = images[src] = {
|
||||||
img: img
|
img: img
|
||||||
};
|
};
|
||||||
images.numTotal++;
|
images.numTotal++;
|
||||||
setImageLoadHandlers(img, imageObj);
|
setImageLoadHandlers(img, imageObj);
|
||||||
img.src = src;
|
img.src = src;
|
||||||
} else if ( supportCORS && !options.allowTaint && options.useCORS ) {
|
} else if ( supportCORS && !options.allowTaint && options.useCORS ) {
|
||||||
// attempt to load with CORS
|
// attempt to load with CORS
|
||||||
|
|
||||||
img.crossOrigin = "anonymous";
|
img.crossOrigin = "anonymous";
|
||||||
imageObj = images[src] = {
|
imageObj = images[src] = {
|
||||||
img: img
|
img: img
|
||||||
};
|
};
|
||||||
images.numTotal++;
|
images.numTotal++;
|
||||||
setImageLoadHandlers(img, imageObj);
|
setImageLoadHandlers(img, imageObj);
|
||||||
img.src = src;
|
img.src = src;
|
||||||
|
|
||||||
// work around for https://bugs.webkit.org/show_bug.cgi?id=80028
|
// work around for https://bugs.webkit.org/show_bug.cgi?id=80028
|
||||||
img.customComplete = function () {
|
img.customComplete = function () {
|
||||||
if (!this.img.complete) {
|
if (!this.img.complete) {
|
||||||
this.timer = window.setTimeout(this.img.customComplete, 100);
|
this.timer = window.setTimeout(this.img.customComplete, 100);
|
||||||
} else {
|
} else {
|
||||||
this.img.onerror();
|
this.img.onerror();
|
||||||
}
|
|
||||||
}.bind(imageObj);
|
|
||||||
img.customComplete();
|
|
||||||
|
|
||||||
} else if ( options.proxy ) {
|
|
||||||
imageObj = images[src] = {
|
|
||||||
img: img
|
|
||||||
};
|
|
||||||
images.numTotal++;
|
|
||||||
proxyGetImage( src, img, imageObj );
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}.bind(imageObj);
|
||||||
|
img.customComplete();
|
||||||
|
|
||||||
},
|
} else if ( options.proxy ) {
|
||||||
cleanupDOM: function(cause) {
|
imageObj = images[src] = {
|
||||||
var img, src;
|
img: img
|
||||||
if (!images.cleanupDone) {
|
};
|
||||||
if (cause && typeof cause === "string") {
|
images.numTotal++;
|
||||||
h2clog("html2canvas: Cleanup because: " + cause);
|
proxyGetImage( src, img, imageObj );
|
||||||
} else {
|
}
|
||||||
h2clog("html2canvas: Cleanup after timeout: " + options.timeout + " ms.");
|
}
|
||||||
}
|
|
||||||
|
|
||||||
for (src in images) {
|
},
|
||||||
if (images.hasOwnProperty(src)) {
|
cleanupDOM: function(cause) {
|
||||||
img = images[src];
|
var img, src;
|
||||||
if (typeof img === "object" && img.callbackname && img.succeeded === undefined) {
|
if (!images.cleanupDone) {
|
||||||
// cancel proxy image request
|
if (cause && typeof cause === "string") {
|
||||||
window[img.callbackname] = undefined; // to work with IE<9 // NOTE: that the undefined callback property-name still exists on the window object (for IE<9)
|
h2clog("html2canvas: Cleanup because: " + cause);
|
||||||
try {
|
} else {
|
||||||
delete window[img.callbackname]; // for all browser that support this
|
h2clog("html2canvas: Cleanup after timeout: " + options.timeout + " ms.");
|
||||||
} catch(ex) {}
|
|
||||||
if (img.script && img.script.parentNode) {
|
|
||||||
img.script.setAttribute("src", "about:blank"); // try to cancel running request
|
|
||||||
img.script.parentNode.removeChild(img.script);
|
|
||||||
}
|
|
||||||
images.numLoaded++;
|
|
||||||
images.numFailed++;
|
|
||||||
h2clog("html2canvas: Cleaned up failed img: '" + src + "' Steps: " + images.numLoaded + " / " + images.numTotal);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// cancel any pending requests
|
|
||||||
if(window.stop !== undefined) {
|
|
||||||
window.stop();
|
|
||||||
} else if(document.execCommand !== undefined) {
|
|
||||||
document.execCommand("Stop", false);
|
|
||||||
}
|
|
||||||
if (document.close !== undefined) {
|
|
||||||
document.close();
|
|
||||||
}
|
|
||||||
images.cleanupDone = true;
|
|
||||||
if (!(cause && typeof cause === "string")) {
|
|
||||||
start();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
renderingDone: function() {
|
|
||||||
if (timeoutTimer) {
|
|
||||||
window.clearTimeout(timeoutTimer);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
};
|
for (src in images) {
|
||||||
|
if (images.hasOwnProperty(src)) {
|
||||||
|
img = images[src];
|
||||||
|
if (typeof img === "object" && img.callbackname && img.succeeded === undefined) {
|
||||||
|
// cancel proxy image request
|
||||||
|
window[img.callbackname] = undefined; // to work with IE<9 // NOTE: that the undefined callback property-name still exists on the window object (for IE<9)
|
||||||
|
try {
|
||||||
|
delete window[img.callbackname]; // for all browser that support this
|
||||||
|
} catch(ex) {}
|
||||||
|
if (img.script && img.script.parentNode) {
|
||||||
|
img.script.setAttribute("src", "about:blank"); // try to cancel running request
|
||||||
|
img.script.parentNode.removeChild(img.script);
|
||||||
|
}
|
||||||
|
images.numLoaded++;
|
||||||
|
images.numFailed++;
|
||||||
|
h2clog("html2canvas: Cleaned up failed img: '" + src + "' Steps: " + images.numLoaded + " / " + images.numTotal);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (options.timeout > 0) {
|
// cancel any pending requests
|
||||||
timeoutTimer = window.setTimeout(methods.cleanupDOM, options.timeout);
|
if(window.stop !== undefined) {
|
||||||
}
|
window.stop();
|
||||||
h2clog('html2canvas: Preload starts: finding background-images');
|
} else if(document.execCommand !== undefined) {
|
||||||
images.firstRun = true;
|
document.execCommand("Stop", false);
|
||||||
|
}
|
||||||
getImages( element );
|
if (document.close !== undefined) {
|
||||||
|
document.close();
|
||||||
h2clog('html2canvas: Preload: Finding images');
|
}
|
||||||
// load <img> images
|
images.cleanupDone = true;
|
||||||
for (i = 0; i < imgLen; i+=1){
|
if (!(cause && typeof cause === "string")) {
|
||||||
methods.loadImage( domImages[i].getAttribute( "src" ) );
|
start();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
renderingDone: function() {
|
||||||
|
if (timeoutTimer) {
|
||||||
|
window.clearTimeout(timeoutTimer);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
images.firstRun = false;
|
};
|
||||||
h2clog('html2canvas: Preload: Done.');
|
|
||||||
if ( images.numTotal === images.numLoaded ) {
|
|
||||||
start();
|
|
||||||
}
|
|
||||||
|
|
||||||
return methods;
|
if (options.timeout > 0) {
|
||||||
|
timeoutTimer = window.setTimeout(methods.cleanupDOM, options.timeout);
|
||||||
|
}
|
||||||
|
h2clog('html2canvas: Preload starts: finding background-images');
|
||||||
|
images.firstRun = true;
|
||||||
|
|
||||||
};
|
getImages( element );
|
||||||
|
|
||||||
|
h2clog('html2canvas: Preload: Finding images');
|
||||||
|
// load <img> images
|
||||||
|
for (i = 0; i < imgLen; i+=1){
|
||||||
|
methods.loadImage( domImages[i].getAttribute( "src" ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
images.firstRun = false;
|
||||||
|
h2clog('html2canvas: Preload: Done.');
|
||||||
|
if ( images.numTotal === images.numLoaded ) {
|
||||||
|
start();
|
||||||
|
}
|
||||||
|
|
||||||
|
return methods;
|
||||||
|
|
||||||
|
};
|
145
src/Queue.js
145
src/Queue.js
@ -1,81 +1,74 @@
|
|||||||
/*
|
|
||||||
html2canvas @VERSION@ <http://html2canvas.hertzen.com>
|
|
||||||
Copyright (c) 2011 Niklas von Hertzen. All rights reserved.
|
|
||||||
http://www.twitter.com/niklasvh
|
|
||||||
|
|
||||||
Released under MIT License
|
|
||||||
*/
|
|
||||||
function h2cRenderContext(width, height) {
|
function h2cRenderContext(width, height) {
|
||||||
var storage = [];
|
var storage = [];
|
||||||
return {
|
return {
|
||||||
storage: storage,
|
storage: storage,
|
||||||
width: width,
|
width: width,
|
||||||
height: height,
|
height: height,
|
||||||
fillRect: function () {
|
fillRect: function () {
|
||||||
storage.push({
|
storage.push({
|
||||||
type: "function",
|
type: "function",
|
||||||
name: "fillRect",
|
name: "fillRect",
|
||||||
'arguments': arguments
|
'arguments': arguments
|
||||||
});
|
});
|
||||||
|
},
|
||||||
|
drawShape: function() {
|
||||||
|
|
||||||
|
var shape = [];
|
||||||
|
|
||||||
|
storage.push({
|
||||||
|
type: "function",
|
||||||
|
name: "drawShape",
|
||||||
|
'arguments': shape
|
||||||
|
});
|
||||||
|
|
||||||
|
return {
|
||||||
|
moveTo: function() {
|
||||||
|
shape.push({
|
||||||
|
name: "moveTo",
|
||||||
|
'arguments': arguments
|
||||||
|
});
|
||||||
},
|
},
|
||||||
drawShape: function() {
|
lineTo: function() {
|
||||||
|
shape.push({
|
||||||
var shape = [];
|
name: "lineTo",
|
||||||
|
'arguments': arguments
|
||||||
storage.push({
|
});
|
||||||
type: "function",
|
|
||||||
name: "drawShape",
|
|
||||||
'arguments': shape
|
|
||||||
});
|
|
||||||
|
|
||||||
return {
|
|
||||||
moveTo: function() {
|
|
||||||
shape.push({
|
|
||||||
name: "moveTo",
|
|
||||||
'arguments': arguments
|
|
||||||
});
|
|
||||||
},
|
|
||||||
lineTo: function() {
|
|
||||||
shape.push({
|
|
||||||
name: "lineTo",
|
|
||||||
'arguments': arguments
|
|
||||||
});
|
|
||||||
},
|
|
||||||
bezierCurveTo: function() {
|
|
||||||
shape.push({
|
|
||||||
name: "bezierCurveTo",
|
|
||||||
'arguments': arguments
|
|
||||||
});
|
|
||||||
},
|
|
||||||
quadraticCurveTo: function() {
|
|
||||||
shape.push({
|
|
||||||
name: "quadraticCurveTo",
|
|
||||||
'arguments': arguments
|
|
||||||
});
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
},
|
},
|
||||||
drawImage: function () {
|
bezierCurveTo: function() {
|
||||||
storage.push({
|
shape.push({
|
||||||
type: "function",
|
name: "bezierCurveTo",
|
||||||
name: "drawImage",
|
'arguments': arguments
|
||||||
'arguments': arguments
|
});
|
||||||
});
|
|
||||||
},
|
},
|
||||||
fillText: function () {
|
quadraticCurveTo: function() {
|
||||||
storage.push({
|
shape.push({
|
||||||
type: "function",
|
name: "quadraticCurveTo",
|
||||||
name: "fillText",
|
'arguments': arguments
|
||||||
'arguments': arguments
|
});
|
||||||
});
|
|
||||||
},
|
|
||||||
setVariable: function (variable, value) {
|
|
||||||
storage.push({
|
|
||||||
type: "variable",
|
|
||||||
name: variable,
|
|
||||||
'arguments': value
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
|
||||||
|
},
|
||||||
|
drawImage: function () {
|
||||||
|
storage.push({
|
||||||
|
type: "function",
|
||||||
|
name: "drawImage",
|
||||||
|
'arguments': arguments
|
||||||
|
});
|
||||||
|
},
|
||||||
|
fillText: function () {
|
||||||
|
storage.push({
|
||||||
|
type: "function",
|
||||||
|
name: "fillText",
|
||||||
|
'arguments': arguments
|
||||||
|
});
|
||||||
|
},
|
||||||
|
setVariable: function (variable, value) {
|
||||||
|
storage.push({
|
||||||
|
type: "variable",
|
||||||
|
name: variable,
|
||||||
|
'arguments': value
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
@ -1,66 +1,57 @@
|
|||||||
/*
|
|
||||||
html2canvas @VERSION@ <http://html2canvas.hertzen.com>
|
|
||||||
Copyright (c) 2011 Niklas von Hertzen. All rights reserved.
|
|
||||||
http://www.twitter.com/niklasvh
|
|
||||||
|
|
||||||
Released under MIT License
|
|
||||||
*/
|
|
||||||
_html2canvas.Renderer = function(parseQueue, options){
|
_html2canvas.Renderer = function(parseQueue, options){
|
||||||
|
var queue = [];
|
||||||
|
|
||||||
|
function sortZ(zStack){
|
||||||
|
var subStacks = [],
|
||||||
|
stackValues = [],
|
||||||
|
zStackChildren = zStack.children,
|
||||||
|
s,
|
||||||
|
i,
|
||||||
|
stackLen,
|
||||||
|
zValue,
|
||||||
|
zLen,
|
||||||
|
stackChild,
|
||||||
|
b,
|
||||||
|
subStackLen;
|
||||||
|
|
||||||
|
|
||||||
var queue = [];
|
for (s = 0, zLen = zStackChildren.length; s < zLen; s+=1){
|
||||||
|
|
||||||
function sortZ(zStack){
|
stackChild = zStackChildren[s];
|
||||||
var subStacks = [],
|
|
||||||
stackValues = [],
|
|
||||||
zStackChildren = zStack.children,
|
|
||||||
s,
|
|
||||||
i,
|
|
||||||
stackLen,
|
|
||||||
zValue,
|
|
||||||
zLen,
|
|
||||||
stackChild,
|
|
||||||
b,
|
|
||||||
subStackLen;
|
|
||||||
|
|
||||||
|
if (stackChild.children && stackChild.children.length > 0){
|
||||||
for (s = 0, zLen = zStackChildren.length; s < zLen; s+=1){
|
subStacks.push(stackChild);
|
||||||
|
stackValues.push(stackChild.zindex);
|
||||||
stackChild = zStackChildren[s];
|
}else{
|
||||||
|
queue.push(stackChild);
|
||||||
if (stackChild.children && stackChild.children.length > 0){
|
}
|
||||||
subStacks.push(stackChild);
|
|
||||||
stackValues.push(stackChild.zindex);
|
|
||||||
}else{
|
|
||||||
queue.push(stackChild);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
stackValues.sort(function(a, b) {
|
|
||||||
return a - b;
|
|
||||||
});
|
|
||||||
|
|
||||||
for (i = 0, stackLen = stackValues.length; i < stackLen; i+=1){
|
|
||||||
zValue = stackValues[i];
|
|
||||||
for (b = 0, subStackLen = subStacks.length; b <= subStackLen; b+=1){
|
|
||||||
|
|
||||||
if (subStacks[b].zindex === zValue){
|
|
||||||
stackChild = subStacks.splice(b, 1);
|
|
||||||
sortZ(stackChild[0]);
|
|
||||||
break;
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
stackValues.sort(function(a, b) {
|
||||||
|
return a - b;
|
||||||
|
});
|
||||||
|
|
||||||
sortZ(parseQueue.zIndex);
|
for (i = 0, stackLen = stackValues.length; i < stackLen; i+=1){
|
||||||
if ( typeof options._renderer._create !== "function" ) {
|
zValue = stackValues[i];
|
||||||
throw new Error("Invalid renderer defined");
|
for (b = 0, subStackLen = subStacks.length; b <= subStackLen; b+=1){
|
||||||
|
|
||||||
|
if (subStacks[b].zindex === zValue){
|
||||||
|
stackChild = subStacks.splice(b, 1);
|
||||||
|
sortZ(stackChild[0]);
|
||||||
|
break;
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return options._renderer._create( parseQueue, options, document, queue, _html2canvas );
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
sortZ(parseQueue.zIndex);
|
||||||
|
if ( typeof options._renderer._create !== "function" ) {
|
||||||
|
throw new Error("Invalid renderer defined");
|
||||||
|
}
|
||||||
|
return options._renderer._create( parseQueue, options, document, queue, _html2canvas );
|
||||||
|
|
||||||
};
|
};
|
||||||
|
145
src/Util.js
145
src/Util.js
@ -1,98 +1,89 @@
|
|||||||
/*
|
|
||||||
html2canvas @VERSION@ <http://html2canvas.hertzen.com>
|
|
||||||
Copyright (c) 2011 Niklas von Hertzen. All rights reserved.
|
|
||||||
http://www.twitter.com/niklasvh
|
|
||||||
|
|
||||||
Released under MIT License
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
html2canvas = function( elements, opts ) {
|
html2canvas = function( elements, opts ) {
|
||||||
|
|
||||||
var queue,
|
var queue,
|
||||||
canvas,
|
canvas,
|
||||||
options = {
|
options = {
|
||||||
// general
|
// general
|
||||||
logging: false,
|
logging: false,
|
||||||
elements: elements,
|
elements: elements,
|
||||||
|
|
||||||
// preload options
|
// preload options
|
||||||
proxy: "http://html2canvas.appspot.com/",
|
proxy: "http://html2canvas.appspot.com/",
|
||||||
timeout: 0, // no timeout
|
timeout: 0, // no timeout
|
||||||
useCORS: false, // try to load images as CORS (where available), before falling back to proxy
|
useCORS: false, // try to load images as CORS (where available), before falling back to proxy
|
||||||
allowTaint: false, // whether to allow images to taint the canvas, won't need proxy if set to true
|
allowTaint: false, // whether to allow images to taint the canvas, won't need proxy if set to true
|
||||||
|
|
||||||
// parse options
|
// parse options
|
||||||
svgRendering: false, // use svg powered rendering where available (FF11+)
|
svgRendering: false, // use svg powered rendering where available (FF11+)
|
||||||
iframeDefault: "default",
|
iframeDefault: "default",
|
||||||
ignoreElements: "IFRAME|OBJECT|PARAM",
|
ignoreElements: "IFRAME|OBJECT|PARAM",
|
||||||
useOverflow: true,
|
useOverflow: true,
|
||||||
letterRendering: false,
|
letterRendering: false,
|
||||||
|
|
||||||
// render options
|
// render options
|
||||||
|
|
||||||
flashcanvas: undefined, // path to flashcanvas
|
flashcanvas: undefined, // path to flashcanvas
|
||||||
width: null,
|
width: null,
|
||||||
height: null,
|
height: null,
|
||||||
taintTest: true, // do a taint test with all images before applying to canvas
|
taintTest: true, // do a taint test with all images before applying to canvas
|
||||||
renderer: "Canvas"
|
renderer: "Canvas"
|
||||||
}, renderer;
|
}, renderer;
|
||||||
|
|
||||||
options = _html2canvas.Util.Extend(opts, options);
|
options = _html2canvas.Util.Extend(opts, options);
|
||||||
|
|
||||||
if (typeof options.renderer === "string" && _html2canvas.Renderer[options.renderer] !== undefined) {
|
if (typeof options.renderer === "string" && _html2canvas.Renderer[options.renderer] !== undefined) {
|
||||||
options._renderer = _html2canvas.Renderer[options.renderer]( options );
|
options._renderer = _html2canvas.Renderer[options.renderer]( options );
|
||||||
} else if (typeof options.renderer === "function") {
|
} else if (typeof options.renderer === "function") {
|
||||||
options._renderer = options.renderer( options );
|
options._renderer = options.renderer( options );
|
||||||
} else {
|
} else {
|
||||||
throw("Unknown renderer");
|
throw("Unknown renderer");
|
||||||
}
|
}
|
||||||
|
|
||||||
_html2canvas.logging = options.logging;
|
_html2canvas.logging = options.logging;
|
||||||
options.complete = function( images ) {
|
options.complete = function( images ) {
|
||||||
|
|
||||||
if (typeof options.onpreloaded === "function") {
|
if (typeof options.onpreloaded === "function") {
|
||||||
if ( options.onpreloaded( images ) === false ) {
|
if ( options.onpreloaded( images ) === false ) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
queue = _html2canvas.Parse( images, options );
|
queue = _html2canvas.Parse( images, options );
|
||||||
|
|
||||||
if (typeof options.onparsed === "function") {
|
if (typeof options.onparsed === "function") {
|
||||||
if ( options.onparsed( queue ) === false ) {
|
if ( options.onparsed( queue ) === false ) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
canvas = _html2canvas.Renderer( queue, options );
|
canvas = _html2canvas.Renderer( queue, options );
|
||||||
|
|
||||||
if (typeof options.onrendered === "function") {
|
if (typeof options.onrendered === "function") {
|
||||||
options.onrendered( canvas );
|
options.onrendered( canvas );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// for pages without images, we still want this to be async, i.e. return methods before executing
|
// for pages without images, we still want this to be async, i.e. return methods before executing
|
||||||
window.setTimeout( function(){
|
window.setTimeout( function(){
|
||||||
_html2canvas.Preload( options );
|
_html2canvas.Preload( options );
|
||||||
}, 0 );
|
}, 0 );
|
||||||
|
|
||||||
return {
|
return {
|
||||||
render: function( queue, opts ) {
|
render: function( queue, opts ) {
|
||||||
return _html2canvas.Renderer( queue, _html2canvas.Util.Extend(opts, options) );
|
return _html2canvas.Renderer( queue, _html2canvas.Util.Extend(opts, options) );
|
||||||
},
|
},
|
||||||
parse: function( images, opts ) {
|
parse: function( images, opts ) {
|
||||||
return _html2canvas.Parse( images, _html2canvas.Util.Extend(opts, options) );
|
return _html2canvas.Parse( images, _html2canvas.Util.Extend(opts, options) );
|
||||||
},
|
},
|
||||||
preload: function( opts ) {
|
preload: function( opts ) {
|
||||||
return _html2canvas.Preload( _html2canvas.Util.Extend(opts, options) );
|
return _html2canvas.Preload( _html2canvas.Util.Extend(opts, options) );
|
||||||
},
|
},
|
||||||
log: h2clog
|
log: h2clog
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
html2canvas.log = h2clog; // for renderers
|
html2canvas.log = h2clog; // for renderers
|
||||||
html2canvas.Renderer = {
|
html2canvas.Renderer = {
|
||||||
Canvas: undefined // We are assuming this will be used
|
Canvas: undefined // We are assuming this will be used
|
||||||
};
|
};
|
@ -1,2 +0,0 @@
|
|||||||
window.html2canvas = html2canvas;
|
|
||||||
}(window, document));
|
|
@ -1 +0,0 @@
|
|||||||
(function(window, document, undefined){
|
|
@ -1,225 +1,216 @@
|
|||||||
/*
|
|
||||||
html2canvas @VERSION@ <http://html2canvas.hertzen.com>
|
|
||||||
Copyright (c) 2011 Niklas von Hertzen. All rights reserved.
|
|
||||||
http://www.twitter.com/niklasvh
|
|
||||||
|
|
||||||
Released under MIT License
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
_html2canvas.Renderer.Canvas = function( options ) {
|
_html2canvas.Renderer.Canvas = function( options ) {
|
||||||
|
|
||||||
options = options || {};
|
options = options || {};
|
||||||
|
|
||||||
var doc = document,
|
var doc = document,
|
||||||
canvas = options.canvas || doc.createElement('canvas'),
|
canvas = options.canvas || doc.createElement('canvas'),
|
||||||
usingFlashcanvas = false,
|
usingFlashcanvas = false,
|
||||||
_createCalled = false,
|
_createCalled = false,
|
||||||
canvasReadyToDraw = false,
|
canvasReadyToDraw = false,
|
||||||
methods,
|
methods,
|
||||||
flashMaxSize = 2880; // flash bitmap limited to 2880x2880px // http://stackoverflow.com/questions/2033792/argumenterror-error-2015-invalid-bitmapdata
|
flashMaxSize = 2880; // flash bitmap limited to 2880x2880px // http://stackoverflow.com/questions/2033792/argumenterror-error-2015-invalid-bitmapdata
|
||||||
|
|
||||||
|
|
||||||
if (canvas.getContext){
|
if (canvas.getContext){
|
||||||
h2clog("html2canvas: Renderer: using canvas renderer");
|
h2clog("html2canvas: Renderer: using canvas renderer");
|
||||||
|
canvasReadyToDraw = true;
|
||||||
|
} else if ( options.flashcanvas !== undefined ){
|
||||||
|
usingFlashcanvas = true;
|
||||||
|
h2clog("html2canvas: Renderer: canvas not available, using flashcanvas");
|
||||||
|
var script = doc.createElement("script");
|
||||||
|
script.src = options.flashcanvas;
|
||||||
|
|
||||||
|
script.onload = (function(script, func){
|
||||||
|
var intervalFunc;
|
||||||
|
|
||||||
|
if (script.onload === undefined) {
|
||||||
|
// IE lack of support for script onload
|
||||||
|
|
||||||
|
if( script.onreadystatechange !== undefined ) {
|
||||||
|
|
||||||
|
intervalFunc = function() {
|
||||||
|
if (script.readyState !== "loaded" && script.readyState !== "complete") {
|
||||||
|
window.setTimeout( intervalFunc, 250 );
|
||||||
|
|
||||||
|
} else {
|
||||||
|
// it is loaded
|
||||||
|
func();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
window.setTimeout( intervalFunc, 250 );
|
||||||
|
|
||||||
|
} else {
|
||||||
|
h2clog("html2canvas: Renderer: Can't track when flashcanvas is loaded");
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
return func;
|
||||||
|
}
|
||||||
|
|
||||||
|
})(script, function(){
|
||||||
|
|
||||||
|
if (typeof window.FlashCanvas !== "undefined") {
|
||||||
|
h2clog("html2canvas: Renderer: Flashcanvas initialized");
|
||||||
|
window.FlashCanvas.initElement( canvas );
|
||||||
|
|
||||||
canvasReadyToDraw = true;
|
canvasReadyToDraw = true;
|
||||||
} else if ( options.flashcanvas !== undefined ){
|
if ( _createCalled !== false ) {
|
||||||
usingFlashcanvas = true;
|
methods._create.apply( null, _createCalled );
|
||||||
h2clog("html2canvas: Renderer: canvas not available, using flashcanvas");
|
}
|
||||||
var script = doc.createElement("script");
|
}
|
||||||
script.src = options.flashcanvas;
|
});
|
||||||
|
|
||||||
script.onload = (function(script, func){
|
doc.body.appendChild( script );
|
||||||
var intervalFunc;
|
|
||||||
|
|
||||||
if (script.onload === undefined) {
|
}
|
||||||
// IE lack of support for script onload
|
|
||||||
|
|
||||||
if( script.onreadystatechange !== undefined ) {
|
methods = {
|
||||||
|
_create: function( zStack, options, doc, queue, _html2canvas ) {
|
||||||
|
|
||||||
intervalFunc = function() {
|
if ( !canvasReadyToDraw ) {
|
||||||
if (script.readyState !== "loaded" && script.readyState !== "complete") {
|
_createCalled = arguments;
|
||||||
window.setTimeout( intervalFunc, 250 );
|
return canvas;
|
||||||
|
}
|
||||||
|
|
||||||
} else {
|
var ctx = canvas.getContext("2d"),
|
||||||
// it is loaded
|
storageContext,
|
||||||
func();
|
i,
|
||||||
|
queueLen,
|
||||||
|
a,
|
||||||
|
newCanvas,
|
||||||
|
bounds,
|
||||||
|
testCanvas = document.createElement("canvas"),
|
||||||
|
hasCTX = ( testCanvas.getContext !== undefined ),
|
||||||
|
storageLen,
|
||||||
|
renderItem,
|
||||||
|
testctx = ( hasCTX ) ? testCanvas.getContext("2d") : {},
|
||||||
|
safeImages = [],
|
||||||
|
fstyle;
|
||||||
|
|
||||||
|
canvas.width = canvas.style.width = (!usingFlashcanvas) ? options.width || zStack.ctx.width : Math.min(flashMaxSize, (options.width || zStack.ctx.width) );
|
||||||
|
canvas.height = canvas.style.height = (!usingFlashcanvas) ? options.height || zStack.ctx.height : Math.min(flashMaxSize, (options.height || zStack.ctx.height) );
|
||||||
|
|
||||||
|
fstyle = ctx.fillStyle;
|
||||||
|
ctx.fillStyle = zStack.backgroundColor;
|
||||||
|
ctx.fillRect(0, 0, canvas.width, canvas.height);
|
||||||
|
ctx.fillStyle = fstyle;
|
||||||
|
|
||||||
|
var drawShape = function(args) {
|
||||||
|
|
||||||
|
var i, len = args.length;
|
||||||
|
ctx.beginPath();
|
||||||
|
for ( i = 0; i < len; i++ ) {
|
||||||
|
ctx[ args[ i ].name ].apply( ctx, args[ i ]['arguments'] );
|
||||||
|
}
|
||||||
|
ctx.closePath();
|
||||||
|
ctx.fill();
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
if ( options.svgRendering && zStack.svgRender !== undefined ) {
|
||||||
|
// TODO: enable async rendering to support this
|
||||||
|
ctx.drawImage( zStack.svgRender, 0, 0 );
|
||||||
|
} else {
|
||||||
|
for ( i = 0, queueLen = queue.length; i < queueLen; i+=1 ) {
|
||||||
|
|
||||||
|
storageContext = queue.splice(0, 1)[0];
|
||||||
|
storageContext.canvasPosition = storageContext.canvasPosition || {};
|
||||||
|
|
||||||
|
//this.canvasRenderContext(storageContext,parentctx);
|
||||||
|
|
||||||
|
// set common settings for canvas
|
||||||
|
ctx.textBaseline = "bottom";
|
||||||
|
|
||||||
|
if (storageContext.clip){
|
||||||
|
ctx.save();
|
||||||
|
ctx.beginPath();
|
||||||
|
// console.log(storageContext);
|
||||||
|
ctx.rect(storageContext.clip.left, storageContext.clip.top, storageContext.clip.width, storageContext.clip.height);
|
||||||
|
ctx.clip();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if (storageContext.ctx.storage){
|
||||||
|
|
||||||
|
for (a = 0, storageLen = storageContext.ctx.storage.length; a < storageLen; a+=1){
|
||||||
|
|
||||||
|
renderItem = storageContext.ctx.storage[a];
|
||||||
|
|
||||||
|
|
||||||
|
switch(renderItem.type){
|
||||||
|
case "variable":
|
||||||
|
ctx[renderItem.name] = renderItem['arguments'];
|
||||||
|
break;
|
||||||
|
case "function":
|
||||||
|
if (renderItem.name === "fillRect") {
|
||||||
|
if (!usingFlashcanvas || renderItem['arguments'][0] + renderItem['arguments'][2] < flashMaxSize && renderItem['arguments'][1] + renderItem['arguments'][3] < flashMaxSize) {
|
||||||
|
ctx.fillRect.apply( ctx, renderItem['arguments'] );
|
||||||
|
}
|
||||||
|
} else if (renderItem.name === "drawShape") {
|
||||||
|
drawShape(renderItem['arguments']);
|
||||||
|
} else if (renderItem.name === "fillText") {
|
||||||
|
if (!usingFlashcanvas || renderItem['arguments'][1] < flashMaxSize && renderItem['arguments'][2] < flashMaxSize) {
|
||||||
|
ctx.fillText.apply( ctx, renderItem['arguments'] );
|
||||||
|
}
|
||||||
|
} else if (renderItem.name === "drawImage") {
|
||||||
|
|
||||||
|
if (renderItem['arguments'][8] > 0 && renderItem['arguments'][7]){
|
||||||
|
if ( hasCTX && options.taintTest ) {
|
||||||
|
if ( safeImages.indexOf( renderItem['arguments'][ 0 ].src ) === -1 ) {
|
||||||
|
testctx.drawImage( renderItem['arguments'][ 0 ], 0, 0 );
|
||||||
|
try {
|
||||||
|
testctx.getImageData( 0, 0, 1, 1 );
|
||||||
|
} catch(e) {
|
||||||
|
testCanvas = doc.createElement("canvas");
|
||||||
|
testctx = testCanvas.getContext("2d");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
safeImages.push( renderItem['arguments'][ 0 ].src );
|
||||||
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
};
|
ctx.drawImage.apply( ctx, renderItem['arguments'] );
|
||||||
|
|
||||||
window.setTimeout( intervalFunc, 250 );
|
|
||||||
|
|
||||||
} else {
|
|
||||||
h2clog("html2canvas: Renderer: Can't track when flashcanvas is loaded");
|
|
||||||
}
|
|
||||||
|
|
||||||
} else {
|
|
||||||
return func;
|
|
||||||
}
|
|
||||||
|
|
||||||
})(script, function(){
|
|
||||||
|
|
||||||
if (typeof window.FlashCanvas !== "undefined") {
|
|
||||||
h2clog("html2canvas: Renderer: Flashcanvas initialized");
|
|
||||||
window.FlashCanvas.initElement( canvas );
|
|
||||||
|
|
||||||
canvasReadyToDraw = true;
|
|
||||||
if ( _createCalled !== false ) {
|
|
||||||
methods._create.apply( null, _createCalled );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
doc.body.appendChild( script );
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
methods = {
|
|
||||||
_create: function( zStack, options, doc, queue, _html2canvas ) {
|
|
||||||
|
|
||||||
if ( !canvasReadyToDraw ) {
|
|
||||||
_createCalled = arguments;
|
|
||||||
return canvas;
|
|
||||||
}
|
|
||||||
|
|
||||||
var ctx = canvas.getContext("2d"),
|
|
||||||
storageContext,
|
|
||||||
i,
|
|
||||||
queueLen,
|
|
||||||
a,
|
|
||||||
newCanvas,
|
|
||||||
bounds,
|
|
||||||
testCanvas = document.createElement("canvas"),
|
|
||||||
hasCTX = ( testCanvas.getContext !== undefined ),
|
|
||||||
storageLen,
|
|
||||||
renderItem,
|
|
||||||
testctx = ( hasCTX ) ? testCanvas.getContext("2d") : {},
|
|
||||||
safeImages = [],
|
|
||||||
fstyle;
|
|
||||||
|
|
||||||
canvas.width = canvas.style.width = (!usingFlashcanvas) ? options.width || zStack.ctx.width : Math.min(flashMaxSize, (options.width || zStack.ctx.width) );
|
|
||||||
canvas.height = canvas.style.height = (!usingFlashcanvas) ? options.height || zStack.ctx.height : Math.min(flashMaxSize, (options.height || zStack.ctx.height) );
|
|
||||||
|
|
||||||
fstyle = ctx.fillStyle;
|
|
||||||
ctx.fillStyle = zStack.backgroundColor;
|
|
||||||
ctx.fillRect(0, 0, canvas.width, canvas.height);
|
|
||||||
ctx.fillStyle = fstyle;
|
|
||||||
|
|
||||||
if ( options.svgRendering && zStack.svgRender !== undefined ) {
|
|
||||||
// TODO: enable async rendering to support this
|
|
||||||
ctx.drawImage( zStack.svgRender, 0, 0 );
|
|
||||||
} else {
|
|
||||||
for ( i = 0, queueLen = queue.length; i < queueLen; i+=1 ) {
|
|
||||||
|
|
||||||
storageContext = queue.splice(0, 1)[0];
|
|
||||||
storageContext.canvasPosition = storageContext.canvasPosition || {};
|
|
||||||
|
|
||||||
//this.canvasRenderContext(storageContext,parentctx);
|
|
||||||
|
|
||||||
// set common settings for canvas
|
|
||||||
ctx.textBaseline = "bottom";
|
|
||||||
|
|
||||||
if (storageContext.clip){
|
|
||||||
ctx.save();
|
|
||||||
ctx.beginPath();
|
|
||||||
// console.log(storageContext);
|
|
||||||
ctx.rect(storageContext.clip.left, storageContext.clip.top, storageContext.clip.width, storageContext.clip.height);
|
|
||||||
ctx.clip();
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
if (storageContext.ctx.storage){
|
|
||||||
|
|
||||||
for (a = 0, storageLen = storageContext.ctx.storage.length; a < storageLen; a+=1){
|
|
||||||
|
|
||||||
renderItem = storageContext.ctx.storage[a];
|
|
||||||
|
|
||||||
|
|
||||||
switch(renderItem.type){
|
break;
|
||||||
case "variable":
|
default:
|
||||||
ctx[renderItem.name] = renderItem['arguments'];
|
|
||||||
break;
|
|
||||||
case "function":
|
|
||||||
if (renderItem.name === "fillRect") {
|
|
||||||
|
|
||||||
if (!usingFlashcanvas || renderItem['arguments'][0] + renderItem['arguments'][2] < flashMaxSize && renderItem['arguments'][1] + renderItem['arguments'][3] < flashMaxSize) {
|
}
|
||||||
ctx.fillRect.apply( ctx, renderItem['arguments'] );
|
|
||||||
}
|
|
||||||
} else if (renderItem.name === "drawShape") {
|
|
||||||
|
|
||||||
( function( args ) {
|
|
||||||
|
|
||||||
var i, len = args.length;
|
|
||||||
ctx.beginPath();
|
|
||||||
for ( i = 0; i < len; i++ ) {
|
|
||||||
ctx[ args[ i ].name ].apply( ctx, args[ i ]['arguments'] );
|
|
||||||
}
|
|
||||||
ctx.closePath();
|
|
||||||
ctx.fill();
|
|
||||||
})( renderItem['arguments'] );
|
|
||||||
|
|
||||||
} else if (renderItem.name === "fillText") {
|
|
||||||
if (!usingFlashcanvas || renderItem['arguments'][1] < flashMaxSize && renderItem['arguments'][2] < flashMaxSize) {
|
|
||||||
ctx.fillText.apply( ctx, renderItem['arguments'] );
|
|
||||||
}
|
|
||||||
} else if (renderItem.name === "drawImage") {
|
|
||||||
|
|
||||||
if (renderItem['arguments'][8] > 0 && renderItem['arguments'][7]){
|
|
||||||
if ( hasCTX && options.taintTest ) {
|
|
||||||
if ( safeImages.indexOf( renderItem['arguments'][ 0 ].src ) === -1 ) {
|
|
||||||
testctx.drawImage( renderItem['arguments'][ 0 ], 0, 0 );
|
|
||||||
try {
|
|
||||||
testctx.getImageData( 0, 0, 1, 1 );
|
|
||||||
} catch(e) {
|
|
||||||
testCanvas = doc.createElement("canvas");
|
|
||||||
testctx = testCanvas.getContext("2d");
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
safeImages.push( renderItem['arguments'][ 0 ].src );
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ctx.drawImage.apply( ctx, renderItem['arguments'] );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
if (storageContext.clip){
|
|
||||||
ctx.restore();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
h2clog("html2canvas: Renderer: Canvas renderer done - returning canvas obj");
|
}
|
||||||
|
if (storageContext.clip){
|
||||||
|
ctx.restore();
|
||||||
|
}
|
||||||
|
|
||||||
queueLen = options.elements.length;
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (queueLen === 1) {
|
h2clog("html2canvas: Renderer: Canvas renderer done - returning canvas obj");
|
||||||
if (typeof options.elements[ 0 ] === "object" && options.elements[ 0 ].nodeName !== "BODY" && usingFlashcanvas === false) {
|
|
||||||
// crop image to the bounds of selected (single) element
|
|
||||||
bounds = _html2canvas.Util.Bounds( options.elements[ 0 ] );
|
|
||||||
newCanvas = doc.createElement('canvas');
|
|
||||||
newCanvas.width = bounds.width;
|
|
||||||
newCanvas.height = bounds.height;
|
|
||||||
ctx = newCanvas.getContext("2d");
|
|
||||||
|
|
||||||
ctx.drawImage( canvas, bounds.left, bounds.top, bounds.width, bounds.height, 0, 0, bounds.width, bounds.height );
|
queueLen = options.elements.length;
|
||||||
canvas = null;
|
|
||||||
return newCanvas;
|
if (queueLen === 1) {
|
||||||
}
|
if (typeof options.elements[ 0 ] === "object" && options.elements[ 0 ].nodeName !== "BODY" && usingFlashcanvas === false) {
|
||||||
} /*else {
|
// crop image to the bounds of selected (single) element
|
||||||
|
bounds = _html2canvas.Util.Bounds( options.elements[ 0 ] );
|
||||||
|
newCanvas = doc.createElement('canvas');
|
||||||
|
newCanvas.width = bounds.width;
|
||||||
|
newCanvas.height = bounds.height;
|
||||||
|
ctx = newCanvas.getContext("2d");
|
||||||
|
|
||||||
|
ctx.drawImage( canvas, bounds.left, bounds.top, bounds.width, bounds.height, 0, 0, bounds.width, bounds.height );
|
||||||
|
canvas = null;
|
||||||
|
return newCanvas;
|
||||||
|
}
|
||||||
|
} /*else {
|
||||||
// TODO clip and resize multiple elements
|
// TODO clip and resize multiple elements
|
||||||
|
|
||||||
for ( i = 0; i < queueLen; i+=1 ) {
|
for ( i = 0; i < queueLen; i+=1 ) {
|
||||||
@ -233,10 +224,10 @@ _html2canvas.Renderer.Canvas = function( options ) {
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
return canvas;
|
return canvas;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
return methods;
|
return methods;
|
||||||
|
|
||||||
};
|
};
|
Loading…
x
Reference in New Issue
Block a user