diff --git a/build.xml b/build.xml
index 552a5f0..af799cd 100644
--- a/build.xml
+++ b/build.xml
@@ -18,6 +18,7 @@
images
for (i = 0; i < imgLen; i+=1){
- methods.loadImage(domImages[i].getAttribute("src"));
+ methods.loadImage( domImages[i].getAttribute( "src" ) );
}
// remove 'start'
- images.splice(0,1);
+ images.splice(0, 1);
- if (images.length === 0){
+ if ( images.length === 0 ) {
start();
}
diff --git a/src/Core.js b/src/Core.js
index 296fbc6..e5ccaad 100644
--- a/src/Core.js
+++ b/src/Core.js
@@ -12,7 +12,11 @@ html2canvas.Util = {};
html2canvas.Util.backgroundImage = function (src) {
- if ( src.substr(0, 5) === 'url("' ) {
+ if (/data:image\/.*;base64,/i.test( src ) || /^(-webkit|-moz|linear-gradient|-o-)/.test( src )) {
+ return src;
+ }
+
+ if (src.toLowerCase().substr( 0, 5 ) === 'url("') {
src = src.substr( 5 );
src = src.substr( 0, src.length - 2 );
} else {
@@ -23,6 +27,41 @@ html2canvas.Util.backgroundImage = function (src) {
return src;
};
+html2canvas.Util.Bounds = function getBounds (el) {
+
+ window.scroll(0,0);
+ var clientRect,
+ bounds = {};
+
+ if (el.getBoundingClientRect){
+ clientRect = el.getBoundingClientRect();
+
+
+ // TODO add scroll position to bounds, so no scrolling of window necessary
+ bounds.top = clientRect.top;
+ bounds.bottom = clientRect.bottom || (clientRect.top + clientRect.height);
+ bounds.left = clientRect.left;
+ bounds.width = clientRect.width;
+ bounds.height = clientRect.height;
+
+ return bounds;
+
+ } /*else{
+
+
+ p = $(el).offset();
+
+ return {
+ left: p.left + getCSS(el,"borderLeftWidth", true),
+ top: p.top + getCSS(el,"borderTopWidth", true),
+ width:$(el).innerWidth(),
+ height:$(el).innerHeight()
+ };
+
+
+ } */
+}
+
html2canvas.Util.getCSS = function (el, attribute) {
// return jQuery(el).css(attribute);
/*
@@ -45,8 +84,8 @@ html2canvas.Util.getCSS = function (el, attribute) {
// If we're not dealing with a regular pixel number
// but a number that has a weird ending, we need to convert it to pixels
- // if ( !/^-?\d+(?:px)?$/i.test( val ) && /^-?\d/.test( val ) ) {
- /*
+ // if ( !/^-?\d+(?:px)?$/i.test( val ) && /^-?\d/.test( val ) ) {
+ /*
// Remember the original values
left = style.left;
@@ -62,8 +101,8 @@ html2canvas.Util.getCSS = function (el, attribute) {
if ( rsLeft ) {
el.runtimeStyle.left = rsLeft;
}*/
- val = $(el).css(attribute);
- // }
+ val = $(el).css(attribute);
+ // }
return val;
diff --git a/src/Generate.js b/src/Generate.js
new file mode 100644
index 0000000..4d76d97
--- /dev/null
+++ b/src/Generate.js
@@ -0,0 +1,109 @@
+html2canvas.Generate = {};
+
+html2canvas.Generate.Gradient = function(src, bounds) {
+ var canvas = document.createElement('canvas'),
+ ctx = canvas.getContext('2d'),
+ tmp,
+ p0 = 0,
+ p1 = 0,
+ p2 = 0,
+ p3 = 0,
+ steps = [],
+ position,
+ i,
+ len,
+ lingrad,
+ increment,
+ p,
+ img;
+
+ canvas.width = bounds.width;
+ canvas.height = bounds.height;
+
+
+ function getColors(input) {
+ var j = -1,
+ color = '',
+ chr;
+
+ while( j++ < input.length ) {
+ chr = input.charAt( j );
+ if (chr === ')') {
+ color += chr;
+ steps.push( color );
+ color = '';
+ j+=2;
+ } else {
+ color += chr;
+ }
+ }
+ }
+
+ if ( tmp = src.match(/-webkit-linear-gradient\((.*)\)/) ) {
+
+ position = tmp[1].split( ",", 1 )[0];
+ getColors( tmp[1].substr( position.length + 2 ) );
+ position = position.split(' ');
+
+ for (p = 0; p < position.length; p+=1) {
+
+ switch(position[p]) {
+ case 'top':
+ p3 = bounds.height;
+ break;
+
+ case 'right':
+ p0 = bounds.width;
+ break;
+
+ case 'bottom':
+ p1 = bounds.height;
+ break;
+
+ case 'left':
+ p2 = bounds.width;
+ break;
+ }
+
+ }
+
+ } else if (tmp = src.match(/-webkit-gradient\(linear, (\d+)% (\d+)\%, (\d+)% (\d+)%, from\((.*)\), to\((.*)\)\)/)) {
+
+ p0 = (tmp[1] * bounds.width) / 100;
+ p1 = (tmp[2] * bounds.height) / 100;
+ p2 = (tmp[3] * bounds.width) / 100;
+ p3 = (tmp[4] * bounds.height) / 100;
+
+ steps.push(tmp[5]);
+ steps.push(tmp[6]);
+
+ } else if (tmp = src.match(/-moz-linear-gradient\((\d+)% (\d+)%, (.*)\)/)) {
+
+ p0 = (tmp[1] * bounds.width) / 100;
+ p1 = (tmp[2] * bounds.width) / 100;
+ p2 = bounds.width - p0;
+ p3 = bounds.height - p1;
+ getColors( tmp[3] );
+
+ } else {
+ return;
+ }
+
+ lingrad = ctx.createLinearGradient( p0, p1, p2, p3 );
+ increment = 1 / (steps.length - 1);
+
+ for (i = 0, len = steps.length; i < len; i+=1) {
+ lingrad.addColorStop(increment * i, steps[i]);
+ }
+
+ ctx.fillStyle = lingrad;
+
+ // draw shapes
+ ctx.fillRect(0, 0, bounds.width,bounds.height);
+
+ img = new Image();
+ img.src = canvas.toDataURL();
+
+ return img;
+
+}
\ No newline at end of file
diff --git a/src/Parse.js b/src/Parse.js
index 094b3e0..a2463b8 100644
--- a/src/Parse.js
+++ b/src/Parse.js
@@ -116,41 +116,6 @@ html2canvas.Parse = function (element, images, opts) {
}
- function getBounds (el) {
-
- window.scroll(0,0);
- var clientRect,
- bounds = {};
-
- if (el.getBoundingClientRect){
- clientRect = el.getBoundingClientRect();
-
-
- // TODO add scroll position to bounds, so no scrolling of window necessary
- bounds.top = clientRect.top;
- bounds.bottom = clientRect.bottom || (clientRect.top + clientRect.height);
- bounds.left = clientRect.left;
- bounds.width = clientRect.width;
- bounds.height = clientRect.height;
-
- return bounds;
-
- } /*else{
-
-
- p = $(el).offset();
-
- return {
- left: p.left + getCSS(el,"borderLeftWidth", true),
- top: p.top + getCSS(el,"borderTopWidth", true),
- width:$(el).innerWidth(),
- height:$(el).innerHeight()
- };
-
-
- } */
- }
-
function textTransform (text, transform) {
switch(transform){
case "lowercase":
@@ -379,7 +344,7 @@ html2canvas.Parse = function (element, images, opts) {
wrapElement.appendChild(oldTextNode.cloneNode(true));
parent.replaceChild(wrapElement, oldTextNode);
- bounds = getBounds(wrapElement);
+ bounds = html2canvas.Util.Bounds(wrapElement);
textValue = oldTextNode.nodeValue;
@@ -489,19 +454,6 @@ html2canvas.Parse = function (element, images, opts) {
}
- function backgroundUrl (src){
- if (src.substr(0,5) === 'url("'){
- src = src.substr(5);
- src = src.substr(0,src.length-2);
- }else{
- src = src.substr(4);
- src = src.substr(0,src.length-1);
- }
-
- return src;
- }
-
-
function renderBorders(el, ctx, bounds, clip){
/*
@@ -781,7 +733,7 @@ html2canvas.Parse = function (element, images, opts) {
function renderBackground(el,bounds,ctx){
// TODO add support for multi background-images
- var background_image = getCSS(el, "backgroundImage", false).split(",")[0],
+ var background_image = getCSS(el, "backgroundImage", false),
background_repeat = getCSS(el, "backgroundRepeat", false).split(",")[0],
image,
bgp,
@@ -796,24 +748,29 @@ html2canvas.Parse = function (element, images, opts) {
height,
add;
- if (typeof background_image !== "undefined" && /^(1|none)$/.test(background_image) === false && /^(-webkit|-moz|linear-gradient|-o-)/.test(background_image)===false){
-
- background_image = backgroundUrl(background_image);
- image = loadImage(background_image);
+ // if (typeof background_image !== "undefined" && /^(1|none)$/.test(background_image) === false && /^(-webkit|-moz|linear-gradient|-o-)/.test(background_image)===false){
+
+ if ( !/data:image\/.*;base64,/i.test(background_image) && !/^(-webkit|-moz|linear-gradient|-o-)/.test(background_image) ) {
+ background_image = background_image.split(",")[0];
+ }
+
+ if ( typeof background_image !== "undefined" && /^(1|none)$/.test( background_image ) === false ) {
+ background_image = html2canvas.Util.backgroundImage( background_image );
+ image = loadImage( background_image );
bgp = getBackgroundPosition(el, bounds, image);
- if (image){
- switch(background_repeat){
+ if ( image ){
+ switch ( background_repeat ) {
case "repeat-x":
- renderBackgroundRepeatX(ctx, image, bgp, bounds.left, bounds.top, bounds.width, bounds.height);
+ renderBackgroundRepeatX( ctx, image, bgp, bounds.left, bounds.top, bounds.width, bounds.height );
break;
case "repeat-y":
- renderBackgroundRepeatY(ctx, image, bgp, bounds.left, bounds.top, bounds.width, bounds.height);
+ renderBackgroundRepeatY( ctx, image, bgp, bounds.left, bounds.top, bounds.width, bounds.height );
break;
case "no-repeat":
@@ -934,7 +891,7 @@ html2canvas.Parse = function (element, images, opts) {
function renderElement(el, parentStack){
- var bounds = getBounds(el),
+ var bounds = html2canvas.Util.Bounds(el),
x = bounds.left,
y = bounds.top,
w = bounds.width,
@@ -984,8 +941,8 @@ html2canvas.Parse = function (element, images, opts) {
if (parentStack.clip){
stack.clip = html2canvas.Util.Extend( {}, parentStack.clip );
- //stack.clip = parentStack.clip;
- // stack.clip.height = stack.clip.height - parentStack.borders[2].width;
+ //stack.clip = parentStack.clip;
+ // stack.clip.height = stack.clip.height - parentStack.borders[2].width;
}
@@ -1016,7 +973,7 @@ html2canvas.Parse = function (element, images, opts) {
stack.clip.width = stack.clip.width-(borders[1].width);
stack.clip.height = stack.clip.height-(borders[2].width);
}
- */
+ */
if (ignoreElementsRegExp.test(el.nodeName) && options.iframeDefault !== "transparent"){
if (options.iframeDefault === "default"){
bgcolor = "#efefef";
@@ -1104,7 +1061,7 @@ html2canvas.Parse = function (element, images, opts) {
},
formValue:true
},stack);
- */
+ */
}
break;
case "TEXTAREA":
diff --git a/src/Preload.js b/src/Preload.js
index d8c93ce..1465b25 100644
--- a/src/Preload.js
+++ b/src/Preload.js
@@ -89,7 +89,7 @@ html2canvas.Preload = function(element, opts){
img.src = a;
}
- delete window[callback_name];
+ delete window[callback_name];
};
count += 1;
@@ -147,7 +147,9 @@ html2canvas.Preload = function(element, opts){
i,
contentsLen = contents.length,
background_image,
- src;
+ src,
+ img;
+
for (i = 0; i < contentsLen; i+=1 ){
// var ignRe = new RegExp("("+this.ignoreElements+")");
// if (!ignRe.test(element.nodeName)){
@@ -160,52 +162,78 @@ html2canvas.Preload = function(element, opts){
if (el.nodeType === 1 || el.nodeType === undefined){
background_image = html2canvas.Util.getCSS(el, 'backgroundImage');
+
+ if ( background_image && background_image !== "1" && background_image !== "none" ) {
+
+ // TODO add multi image background support
+
+ if (background_image.substring(0,7) === "-webkit" || background_image.substring(0,3) === "-o-" || background_image.substring(0,4) === "-moz") {
+
+ img = html2canvas.Generate.Gradient( background_image, html2canvas.Util.Bounds( el ) );
+
+ if ( img !== undefined ){
+ images.push(background_image);
+ images.push(img);
+ imagesLoaded++;
+ 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);
+ methods.loadImage(src); */
}
}
}
methods = {
- loadImage: function(src){
+ loadImage: function( src ) {
var img;
- if (getIndex(images, src) === -1){
- if(src.substr(0, 5) === 'data:'){
- //Base64 src
- images.push(src);
+ if ( getIndex(images, src) === -1 ) {
+ if ( src.match(/data:image\/.*;base64,/i) ) {
+
+ //Base64 src
img = new Image();
- img.src = src;
- images.push(img);
+ img.src = src.replace(/url\(['"]{0,}|['"]{0,}\)$/ig, '');
+
+ images.push( src );
+ images.push( img );
+
imagesLoaded+=1;
start();
- }else if (isSameOrigin(src)){
+
+ }else if ( isSameOrigin( src ) ) {
- images.push(src);
+ images.push( src );
img = new Image();
- img.onload = function(){
+ img.onload = function() {
imagesLoaded+=1;
start();
};
- img.onerror = function(){
- images.splice(getIndex(images, img.src), 2);
+ img.onerror = function() {
+ images.splice( getIndex( images, img.src ), 2 );
start();
};
img.src = src;
images.push(img);
- }else if (options.proxy){
+ }else if ( options.proxy ){
// console.log('b'+src);
- images.push(src);
+ images.push( src );
img = new Image();
- proxyGetImage(src, img);
- images.push(img);
+ proxyGetImage( src, img );
+ images.push( img );
}
}
@@ -217,18 +245,18 @@ html2canvas.Preload = function(element, opts){
// add something to array
images.push('start');
- getImages(element);
+ getImages( element );
// load
images
for (i = 0; i < imgLen; i+=1){
- methods.loadImage(domImages[i].getAttribute("src"));
+ methods.loadImage( domImages[i].getAttribute( "src" ) );
}
// remove 'start'
- images.splice(0,1);
+ images.splice(0, 1);
- if (images.length === 0){
+ if ( images.length === 0 ) {
start();
}
diff --git a/tests/background.html b/tests/background.html
index a77c63f..165ef0a 100644
--- a/tests/background.html
+++ b/tests/background.html
@@ -8,7 +8,7 @@