Skip to content

Commit b65357c

Browse files
committed
added flashcanvas integration and some legacy IE bug fixes
1 parent c4cc1fe commit b65357c

File tree

8 files changed

+9121
-57
lines changed

8 files changed

+9121
-57
lines changed

external/jquery-1.6.2.js

Lines changed: 8966 additions & 3 deletions
Large diffs are not rendered by default.

src/Core.js

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -47,12 +47,14 @@ html2canvas.Util.Bounds = function getBounds (el) {
4747
bounds.top = clientRect.top;
4848
bounds.bottom = clientRect.bottom || (clientRect.top + clientRect.height);
4949
bounds.left = clientRect.left;
50-
bounds.width = clientRect.width;
51-
bounds.height = clientRect.height;
50+
51+
// older IE doesn't have width/height, but top/bottom instead
52+
bounds.width = clientRect.width || (clientRect.right - clientRect.left);
53+
bounds.height = clientRect.height || (clientRect.bottom - clientRect.top);
5254

5355
return bounds;
5456

55-
} /*else{
57+
} /*else{
5658
5759
5860
p = $(el).offset();
@@ -109,6 +111,14 @@ html2canvas.Util.getCSS = function (el, attribute) {
109111
}*/
110112
// val = $(el).css(attribute);
111113
// }
114+
115+
/*
116+
var val = $(el).css(attribute);
117+
118+
if (val === "medium") {
119+
val = 3;
120+
}*/
121+
112122
return $(el).css(attribute);
113123

114124

src/Parse.js

Lines changed: 22 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,8 @@ html2canvas.Parse = function (element, images, opts) {
108108

109109
var getCSS = html2canvas.Util.getCSS;
110110
function getCSSInt(element, attribute) {
111-
return parseInt(getCSS(element, attribute), 10);
111+
var val = parseInt(getCSS(element, attribute), 10);
112+
return (isNaN(val)) ? 0 : val; // borders in old IE are throwing 'medium' for demo.html
112113
}
113114

114115
// Drawing a rectangle
@@ -587,7 +588,7 @@ html2canvas.Parse = function (element, images, opts) {
587588
borders.push({
588589
width: getCSSInt(el, 'border' + sides[s] + 'Width'),
589590
color: getCSS(el, 'border' + sides[s] + 'Color')
590-
});
591+
});
591592
}
592593

593594
return borders;
@@ -662,7 +663,13 @@ html2canvas.Parse = function (element, images, opts) {
662663

663664
for (i = 0, arrLen = cssArr.length; i < arrLen; i+=1){
664665
style = cssArr[i];
666+
667+
try {
665668
valueWrap.style[style] = getCSS(el, style);
669+
} catch( e ) {
670+
// Older IE has issues with "border"
671+
html2canvas.log("html2canvas: Parse: Exception caught in renderFormValue: " + e.message);
672+
}
666673
}
667674

668675

@@ -702,13 +709,22 @@ html2canvas.Parse = function (element, images, opts) {
702709
function getBackgroundPosition(el, bounds, image){
703710
// TODO add support for multi image backgrounds
704711

705-
var bgpos = getCSS(el, "backgroundPosition").split(",")[0] || "0 0",
706-
bgposition = bgpos.split(" "),
712+
var bgposition = (function( bgp ){
713+
714+
if (bgp !== undefined) {
715+
return (bgp.split(",")[0] || "0 0").split(" ");
716+
} else {
717+
// Older IE uses -x and -y
718+
return [ getCSS(el, "backgroundPositionX"), getCSS(el, "backgroundPositionY") ];
719+
}
720+
721+
722+
})( getCSS(el, "backgroundPosition") ),
707723
topPos,
708724
left,
709725
percentage,
710726
val;
711-
727+
712728
if (bgposition.length === 1){
713729
val = bgposition;
714730

@@ -1106,7 +1122,7 @@ html2canvas.Parse = function (element, images, opts) {
11061122

11071123
}
11081124

1109-
1125+
11101126
if (bgbounds.height > 0 && bgbounds.width > 0){
11111127
renderRect(
11121128
ctx,

src/Preload.js

Lines changed: 26 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -63,9 +63,9 @@ html2canvas.Preload = function(element, opts){
6363

6464
function proxyGetImage(url, img){
6565
var callback_name,
66-
scriptUrl = options.proxy,
67-
script,
68-
imgObj = images[url];
66+
scriptUrl = options.proxy,
67+
script,
68+
imgObj = images[url];
6969

7070
link.href = url;
7171
url = link.href; // work around for pages with base href="" set - WARNING: this may change the url -> so access imgObj from images map before changing that url!
@@ -180,8 +180,12 @@ html2canvas.Preload = function(element, opts){
180180

181181
if (elNodeType === 1 || elNodeType === undefined){
182182

183-
background_image = html2canvas.Util.getCSS(el, 'backgroundImage');
184-
183+
// opera throws exception on external-content.html
184+
try {
185+
background_image = html2canvas.Util.getCSS(el, 'backgroundImage');
186+
}catch(e) {
187+
html2canvas.log("html2canvas: failed to get background-image - Exception: " + e.message);
188+
}
185189
if ( background_image && background_image !== "1" && background_image !== "none" ) {
186190

187191
// TODO add multi image background support
@@ -191,7 +195,10 @@ html2canvas.Preload = function(element, opts){
191195
img = html2canvas.Generate.Gradient( background_image, html2canvas.Util.Bounds( el ) );
192196

193197
if ( img !== undefined ){
194-
images[background_image] = { img: img, succeeded: true };
198+
images[background_image] = {
199+
img: img,
200+
succeeded: true
201+
};
195202
images.numTotal++;
196203
images.numLoaded++;
197204
start();
@@ -221,15 +228,20 @@ html2canvas.Preload = function(element, opts){
221228
//Base64 src
222229
img = new Image();
223230
img.src = src.replace(/url\(['"]{0,}|['"]{0,}\)$/ig, '');
224-
images[src] = { img: img, succeeded: true };
231+
images[src] = {
232+
img: img,
233+
succeeded: true
234+
};
225235
images.numTotal++;
226236
images.numLoaded++;
227237
start();
228238

229239
}else if ( isSameOrigin( src ) ) {
230240

231241
img = new Image();
232-
images[src] = { img: img };
242+
images[src] = {
243+
img: img
244+
};
233245
images.numTotal++;
234246

235247
img.onload = function() {
@@ -250,7 +262,9 @@ html2canvas.Preload = function(element, opts){
250262
}else if ( options.proxy ){
251263
// console.log('b'+src);
252264
img = new Image();
253-
images[src] = { img: img };
265+
images[src] = {
266+
img: img
267+
};
254268
images.numTotal++;
255269
proxyGetImage( src, img );
256270
}
@@ -302,9 +316,9 @@ html2canvas.Preload = function(element, opts){
302316
}
303317
},
304318
renderingDone: function() {
305-
if (timeoutTimer) {
306-
window.clearTimeout(timeoutTimer);
307-
}
319+
if (timeoutTimer) {
320+
window.clearTimeout(timeoutTimer);
321+
}
308322
}
309323

310324
};

src/Renderer.js

Lines changed: 77 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@ html2canvas.Renderer = function(parseQueue, opts){
1515
},
1616
queue = [],
1717
canvas,
18+
usingFlashcanvas = false,
19+
flashMaxSize = 2880, // flash bitmap limited to 2880x2880px // http://stackoverflow.com/questions/2033792/argumenterror-error-2015-invalid-bitmapdata
1820
doc = document;
1921

2022
options = html2canvas.Util.Extend(opts, options);
@@ -83,9 +85,9 @@ html2canvas.Renderer = function(parseQueue, opts){
8385
renderItem,
8486
fstyle;
8587

86-
canvas.width = options.width || zStack.ctx.width;
87-
canvas.height = options.height || zStack.ctx.height;
88-
88+
canvas.width = canvas.style.width = (!usingFlashcanvas) ? options.width || zStack.ctx.width : Math.min(flashMaxSize, (options.width || zStack.ctx.width) );
89+
canvas.height = canvas.style.height = (!usingFlashcanvas) ? options.height || zStack.ctx.height : Math.min(flashMaxSize, (options.height || zStack.ctx.height) );
90+
8991
fstyle = ctx.fillStyle;
9092
ctx.fillStyle = "#fff";
9193
ctx.fillRect(0, 0, canvas.width, canvas.height);
@@ -116,29 +118,33 @@ html2canvas.Renderer = function(parseQueue, opts){
116118

117119
renderItem = storageContext.ctx.storage[a];
118120

119-
120121

121122
switch(renderItem.type){
122123
case "variable":
123124
ctx[renderItem.name] = renderItem['arguments'];
124125
break;
125126
case "function":
126127
if (renderItem.name === "fillRect") {
127-
128-
ctx.fillRect(
129-
renderItem['arguments'][0],
130-
renderItem['arguments'][1],
131-
renderItem['arguments'][2],
132-
renderItem['arguments'][3]
133-
);
128+
129+
if (!usingFlashcanvas || renderItem['arguments'][0] + renderItem['arguments'][2] < flashMaxSize && renderItem['arguments'][1] + renderItem['arguments'][3] < flashMaxSize) {
130+
ctx.fillRect(
131+
renderItem['arguments'][0],
132+
renderItem['arguments'][1],
133+
renderItem['arguments'][2],
134+
renderItem['arguments'][3]
135+
);
136+
}
134137
}else if(renderItem.name === "fillText") {
135-
// console.log(renderItem.arguments[0]);
136-
ctx.fillText(renderItem['arguments'][0],renderItem['arguments'][1],renderItem['arguments'][2]);
137-
138+
if (!usingFlashcanvas || renderItem['arguments'][1] < flashMaxSize && renderItem['arguments'][2] < flashMaxSize) {
139+
ctx.fillText(
140+
renderItem['arguments'][0],
141+
renderItem['arguments'][1],
142+
renderItem['arguments'][2]
143+
);
144+
}
138145
}else if(renderItem.name === "drawImage") {
139-
// console.log(renderItem);
140-
// console.log(renderItem.arguments[0].width);
141-
if (renderItem['arguments'][8] > 0 && renderItem['arguments'][7]){
146+
147+
if (renderItem['arguments'][8] > 0 && renderItem['arguments'][7]){
142148
ctx.drawImage(
143149
renderItem['arguments'][0],
144150
renderItem['arguments'][1],
@@ -149,7 +155,7 @@ html2canvas.Renderer = function(parseQueue, opts){
149155
renderItem['arguments'][6],
150156
renderItem['arguments'][7],
151157
renderItem['arguments'][8]
152-
);
158+
);
153159
}
154160
}
155161

@@ -176,20 +182,21 @@ html2canvas.Renderer = function(parseQueue, opts){
176182
queueLen = options.elements.length;
177183

178184
if (queueLen === 1) {
179-
if (options.elements[ 0 ] instanceof Element && options.elements[ 0 ].nodeName !== "BODY") {
185+
if (typeof options.elements[ 0 ] === "object" && options.elements[ 0 ].nodeName !== "BODY" && usingFlashcanvas === false) {
180186
// crop image to the bounds of selected (single) element
181187
bounds = html2canvas.Util.Bounds( options.elements[ 0 ] );
182188
newCanvas = doc.createElement('canvas');
183189
newCanvas.width = bounds.width;
184190
newCanvas.height = bounds.height;
185191
ctx = newCanvas.getContext("2d");
192+
186193
ctx.drawImage( canvas, bounds.left, bounds.top, bounds.width, bounds.height, 0, 0, bounds.width, bounds.height );
187194
delete canvas;
188195
return newCanvas;
189196
}
190197
} else {
191-
// TODO clip and resize multiple elements
192-
/*
198+
// TODO clip and resize multiple elements
199+
/*
193200
for ( i = 0; i < queueLen; i+=1 ) {
194201
if (options.elements[ i ] instanceof Element) {
195202
@@ -400,6 +407,55 @@ html2canvas.Renderer = function(parseQueue, opts){
400407
if (canvas.getContext){
401408
html2canvas.log("html2canvas: Renderer: using canvas renderer");
402409
return canvasRenderer(parseQueue);
410+
} else {
411+
usingFlashcanvas = true;
412+
html2canvas.log("html2canvas: Renderer: canvas not available, using flashcanvas");
413+
var script = doc.createElement("script");
414+
script.src = options.flashcanvas;
415+
416+
script.onload = (function(script, func){
417+
var intervalFunc;
418+
419+
if (script.onload === undefined) {
420+
// IE lack of support for script onload
421+
422+
if( script.onreadystatechange !== undefined ) {
423+
424+
intervalFunc = function() {
425+
if (script.readyState !== "loaded" && script.readyState !== "complete") {
426+
window.setTimeout( intervalFunc, 250 );
427+
428+
} else {
429+
// it is loaded
430+
func();
431+
432+
}
433+
434+
};
435+
436+
window.setTimeout( intervalFunc, 250 );
437+
438+
} else {
439+
html2canvas.log("html2canvas: Renderer: Can't track when flashcanvas is loaded");
440+
441+
}
442+
443+
} else {
444+
return func;
445+
}
446+
447+
})(script, function(){
448+
449+
if (typeof FlashCanvas !== "undefined") {
450+
html2canvas.log("html2canvas: Renderer: Flashcanvas initialized");
451+
FlashCanvas.initElement( canvas );
452+
canvasRenderer(parseQueue);
453+
}
454+
});
455+
456+
doc.body.appendChild( script );
457+
458+
return canvas;
403459
}
404460
break;
405461
case "svg":

src/plugins/jquery.plugin.html2canvas.js

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,10 @@
1212
timer = date.getTime();
1313
options = options || {};
1414
options.elements = this;
15+
options.flashcanvas = "../external/flashcanvas.min.js";
1516

1617
html2canvas.logging = options && options.logging;
17-
html2canvas.Preload(this[0], $.extend({
18-
complete: function(images){
18+
options.complete = function(images){
1919
var queue = html2canvas.Parse(this[0], images, options),
2020
$canvas = $(html2canvas.Renderer(queue, options)),
2121
finishTime = new Date();
@@ -31,8 +31,9 @@
3131
throwMessage("Canvas Render " + ($canvas.is(':visible') ? "visible" : "hidden"));
3232
});
3333
throwMessage('Screenshot created in '+ ((finishTime.getTime()-timer)) + " ms<br />",4000);
34-
}
35-
}, options));
34+
35+
};
36+
html2canvas.Preload(this[0], options);
3637

3738
function throwMessage(msg,duration){
3839
window.clearTimeout(timeoutTimer);

0 commit comments

Comments
 (0)