diff --git a/build.xml b/build.xml
index 46a550558..232c2575b 100644
--- a/build.xml
+++ b/build.xml
@@ -22,6 +22,7 @@
+
diff --git a/readme.md b/readme.md
index 5977f3923..8e1f7ee8d 100644
--- a/readme.md
+++ b/readme.md
@@ -37,6 +37,11 @@ For more information and examples, please visit the niklasvh)
+* Simplified API, cleaned up code (niklasvh)
+
v0.33 - 2.3.2012
* SVG taint fix, and additional taint testing options for rendering (niklasvh)
diff --git a/src/Renderer.js b/src/Renderer.js
index eaf442210..d7fad2ede 100644
--- a/src/Renderer.js
+++ b/src/Renderer.js
@@ -8,15 +8,8 @@
_html2canvas.Renderer = function(parseQueue, options){
- var queue = [],
- canvas,
- usingFlashcanvas = false,
- flashMaxSize = 2880, // flash bitmap limited to 2880x2880px // http://stackoverflow.com/questions/2033792/argumenterror-error-2015-invalid-bitmapdata
- doc = document;
-
-
-
-
+ var queue = [];
+
function sortZ(zStack){
var subStacks = [],
stackValues = [],
@@ -63,411 +56,11 @@ _html2canvas.Renderer = function(parseQueue, options){
}
- function canvasRenderer(zStack){
-
- sortZ(zStack.zIndex);
-
-
- 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;
-
- 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 === "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 = document.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");
-
- // this.canvasRenderStorage(queue,this.ctx);
- queueLen = options.elements.length;
- if (queueLen === 1) {
- 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 );
- canvas = null;
- return newCanvas;
- }
- } /*else {
- // TODO clip and resize multiple elements
-
- for ( i = 0; i < queueLen; i+=1 ) {
- if (options.elements[ i ] instanceof Element) {
-
- }
-
- }
- }
- */
-
-
-
- return canvas;
+ sortZ(parseQueue.zIndex);
+ if ( typeof options.renderer._create !== "function" ) {
+ throw Error("Invalid renderer defined");
}
+ return options.renderer._create( parseQueue, options, document, queue, _html2canvas );
- function svgRenderer(zStack){
- sortZ(zStack.zIndex);
-
- var svgNS = "http://www.w3.org/2000/svg",
- svg = doc.createElementNS(svgNS, "svg"),
- xlinkNS = "http://www.w3.org/1999/xlink",
- defs = doc.createElementNS(svgNS, "defs"),
- i,
- a,
- queueLen,
- storageLen,
- storageContext,
- renderItem,
- el,
- settings = {},
- text,
- fontStyle,
- clipId = 0;
-
- svg.setAttribute("version", "1.1");
- svg.setAttribute("baseProfile", "full");
-
- svg.setAttribute("viewBox", "0 0 " + Math.max(zStack.ctx.width, options.width) + " " + Math.max(zStack.ctx.height, options.height));
- svg.setAttribute("width", Math.max(zStack.ctx.width, options.width) + "px");
- svg.setAttribute("height", Math.max(zStack.ctx.height, options.height) + "px");
- svg.setAttribute("preserveAspectRatio", "none");
- svg.appendChild(defs);
-
-
-
- for (i = 0, queueLen = queue.length; i < queueLen; i+=1){
-
- storageContext = queue.splice(0, 1)[0];
- storageContext.canvasPosition = storageContext.canvasPosition || {};
-
- //this.canvasRenderContext(storageContext,parentctx);
-
-
- /*
- 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":
- settings[renderItem.name] = renderItem['arguments'];
- break;
- case "function":
- if (renderItem.name === "fillRect") {
-
- el = doc.createElementNS(svgNS, "rect");
- el.setAttribute("x", renderItem['arguments'][0]);
- el.setAttribute("y", renderItem['arguments'][1]);
- el.setAttribute("width", renderItem['arguments'][2]);
- el.setAttribute("height", renderItem['arguments'][3]);
- el.setAttribute("fill", settings.fillStyle);
- svg.appendChild(el);
-
- } else if(renderItem.name === "fillText") {
- el = doc.createElementNS(svgNS, "text");
-
- fontStyle = settings.font.split(" ");
-
- el.style.fontVariant = fontStyle.splice(0, 1)[0];
- el.style.fontWeight = fontStyle.splice(0, 1)[0];
- el.style.fontStyle = fontStyle.splice(0, 1)[0];
- el.style.fontSize = fontStyle.splice(0, 1)[0];
-
- el.setAttribute("x", renderItem['arguments'][1]);
- el.setAttribute("y", renderItem['arguments'][2] - (parseInt(el.style.fontSize, 10) + 3));
-
- el.setAttribute("fill", settings.fillStyle);
-
-
-
-
- // TODO get proper baseline
- el.style.dominantBaseline = "text-before-edge";
- el.style.fontFamily = fontStyle.join(" ");
-
- text = doc.createTextNode(renderItem['arguments'][0]);
- el.appendChild(text);
-
-
- svg.appendChild(el);
-
-
-
- } else if(renderItem.name === "drawImage") {
-
- if (renderItem['arguments'][8] > 0 && renderItem['arguments'][7]){
-
- // TODO check whether even any clipping is necessary for this particular image
- el = doc.createElementNS(svgNS, "clipPath");
- el.setAttribute("id", "clipId" + clipId);
-
- text = doc.createElementNS(svgNS, "rect");
- text.setAttribute("x", renderItem['arguments'][5] );
- text.setAttribute("y", renderItem['arguments'][6]);
-
- text.setAttribute("width", renderItem['arguments'][3]);
- text.setAttribute("height", renderItem['arguments'][4]);
- el.appendChild(text);
- defs.appendChild(el);
-
- el = doc.createElementNS(svgNS, "image");
- el.setAttributeNS(xlinkNS, "xlink:href", renderItem['arguments'][0].src);
- el.setAttribute("width", renderItem['arguments'][0].width);
- el.setAttribute("height", renderItem['arguments'][0].height);
- el.setAttribute("x", renderItem['arguments'][5] - renderItem['arguments'][1]);
- el.setAttribute("y", renderItem['arguments'][6] - renderItem['arguments'][2]);
- el.setAttribute("clip-path", "url(#clipId" + clipId + ")");
- // el.setAttribute("xlink:href", );
-
-
- el.setAttribute("preserveAspectRatio", "none");
-
- svg.appendChild(el);
-
-
- clipId += 1;
- /*
- ctx.drawImage(
- renderItem['arguments'][0],
- renderItem['arguments'][1],
- renderItem['arguments'][2],
- renderItem['arguments'][3],
- renderItem['arguments'][4],
- renderItem['arguments'][5],
- renderItem['arguments'][6],
- renderItem['arguments'][7],
- renderItem['arguments'][8]
- );
- */
- }
- }
-
-
-
- break;
- default:
-
- }
-
- }
-
- }
- /*
- if (storageContext.clip){
- ctx.restore();
- }
- */
-
-
-
- }
-
-
-
-
-
-
-
-
-
-
- h2clog("html2canvas: Renderer: SVG Renderer done - returning SVG DOM obj");
-
- return svg;
-
- }
-
-
- //this.each(this.opts.renderOrder.split(" "),function(i,renderer){
-
- //options.renderer = "svg";
-
- switch(options.renderer.toLowerCase()){
- case "canvas":
- canvas = doc.createElement('canvas');
- if (canvas.getContext){
- h2clog("html2canvas: Renderer: using canvas renderer");
- return canvasRenderer(parseQueue);
- } else {
- 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 );
- canvasRenderer(parseQueue);
- }
- });
-
- doc.body.appendChild( script );
-
- return canvas;
- }
- break;
- case "svg":
- if (doc.createElementNS){
- h2clog("html2canvas: Renderer: using SVG renderer");
- return svgRenderer(parseQueue);
- }
- break;
-
- }
-
-
-
- //});
-
-
- return this;
-
-
-
};
diff --git a/src/Util.js b/src/Util.js
index 2c22d5f01..e97125e23 100644
--- a/src/Util.js
+++ b/src/Util.js
@@ -30,15 +30,17 @@ html2canvas = function( elements, opts ) {
// render options
+ flashcanvas: undefined, // path to flashcanvas
width: null,
height: null,
- renderer: "canvas",
taintTest: true // do a taint test with all images before applying to canvas
};
options = _html2canvas.Util.Extend(opts, options);
+ options.renderer = options.renderer || html2canvas.Renderer.Canvas( options );
+
_html2canvas.logging = options.logging;
options.complete = function( images ) {
@@ -82,3 +84,8 @@ html2canvas = function( elements, opts ) {
log: h2clog
};
};
+
+html2canvas.log = h2clog; // for renderers
+html2canvas.Renderer = {
+ Canvas: undefined // We are assuming this will be used
+};
\ No newline at end of file
diff --git a/src/renderers/SVG.js b/src/renderers/SVG.js
new file mode 100644
index 000000000..835a62305
--- /dev/null
+++ b/src/renderers/SVG.js
@@ -0,0 +1,206 @@
+/*
+ html2canvas @VERSION@
+ Copyright (c) 2011 Niklas von Hertzen. All rights reserved.
+ http://www.twitter.com/niklasvh
+
+ Released under MIT License
+*/
+
+
+// WARNING THIS file is outdated, and hasn't been tested in quite a while
+
+html2canvas.Renderer.SVG = function( options ) {
+
+ options = options || {};
+
+ var doc = document,
+ svgNS = "http://www.w3.org/2000/svg",
+ svg = doc.createElementNS(svgNS, "svg"),
+ xlinkNS = "http://www.w3.org/1999/xlink",
+ defs = doc.createElementNS(svgNS, "defs"),
+ i,
+ a,
+ queueLen,
+ storageLen,
+ storageContext,
+ renderItem,
+ el,
+ settings = {},
+ text,
+ fontStyle,
+ clipId = 0,
+ methods;
+
+
+ methods = {
+ _create: function( zStack, options, doc, queue, _html2canvas ) {
+ svg.setAttribute("version", "1.1");
+ svg.setAttribute("baseProfile", "full");
+
+ svg.setAttribute("viewBox", "0 0 " + Math.max(zStack.ctx.width, options.width) + " " + Math.max(zStack.ctx.height, options.height));
+ svg.setAttribute("width", Math.max(zStack.ctx.width, options.width) + "px");
+ svg.setAttribute("height", Math.max(zStack.ctx.height, options.height) + "px");
+ svg.setAttribute("preserveAspectRatio", "none");
+ svg.appendChild(defs);
+
+
+
+ for (i = 0, queueLen = queue.length; i < queueLen; i+=1){
+
+ storageContext = queue.splice(0, 1)[0];
+ storageContext.canvasPosition = storageContext.canvasPosition || {};
+
+ //this.canvasRenderContext(storageContext,parentctx);
+
+
+ /*
+ 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":
+ settings[renderItem.name] = renderItem['arguments'];
+ break;
+ case "function":
+ if (renderItem.name === "fillRect") {
+
+ el = doc.createElementNS(svgNS, "rect");
+ el.setAttribute("x", renderItem['arguments'][0]);
+ el.setAttribute("y", renderItem['arguments'][1]);
+ el.setAttribute("width", renderItem['arguments'][2]);
+ el.setAttribute("height", renderItem['arguments'][3]);
+ el.setAttribute("fill", settings.fillStyle);
+ svg.appendChild(el);
+
+ } else if(renderItem.name === "fillText") {
+ el = doc.createElementNS(svgNS, "text");
+
+ fontStyle = settings.font.split(" ");
+
+ el.style.fontVariant = fontStyle.splice(0, 1)[0];
+ el.style.fontWeight = fontStyle.splice(0, 1)[0];
+ el.style.fontStyle = fontStyle.splice(0, 1)[0];
+ el.style.fontSize = fontStyle.splice(0, 1)[0];
+
+ el.setAttribute("x", renderItem['arguments'][1]);
+ el.setAttribute("y", renderItem['arguments'][2] - (parseInt(el.style.fontSize, 10) + 3));
+
+ el.setAttribute("fill", settings.fillStyle);
+
+
+
+
+ // TODO get proper baseline
+ el.style.dominantBaseline = "text-before-edge";
+ el.style.fontFamily = fontStyle.join(" ");
+
+ text = doc.createTextNode(renderItem['arguments'][0]);
+ el.appendChild(text);
+
+
+ svg.appendChild(el);
+
+
+
+ } else if(renderItem.name === "drawImage") {
+
+ if (renderItem['arguments'][8] > 0 && renderItem['arguments'][7]){
+
+ // TODO check whether even any clipping is necessary for this particular image
+ el = doc.createElementNS(svgNS, "clipPath");
+ el.setAttribute("id", "clipId" + clipId);
+
+ text = doc.createElementNS(svgNS, "rect");
+ text.setAttribute("x", renderItem['arguments'][5] );
+ text.setAttribute("y", renderItem['arguments'][6]);
+
+ text.setAttribute("width", renderItem['arguments'][3]);
+ text.setAttribute("height", renderItem['arguments'][4]);
+ el.appendChild(text);
+ defs.appendChild(el);
+
+ el = doc.createElementNS(svgNS, "image");
+ el.setAttributeNS(xlinkNS, "xlink:href", renderItem['arguments'][0].src);
+ el.setAttribute("width", renderItem['arguments'][0].width);
+ el.setAttribute("height", renderItem['arguments'][0].height);
+ el.setAttribute("x", renderItem['arguments'][5] - renderItem['arguments'][1]);
+ el.setAttribute("y", renderItem['arguments'][6] - renderItem['arguments'][2]);
+ el.setAttribute("clip-path", "url(#clipId" + clipId + ")");
+ // el.setAttribute("xlink:href", );
+
+
+ el.setAttribute("preserveAspectRatio", "none");
+
+ svg.appendChild(el);
+
+
+ clipId += 1;
+ /*
+ ctx.drawImage(
+ renderItem['arguments'][0],
+ renderItem['arguments'][1],
+ renderItem['arguments'][2],
+ renderItem['arguments'][3],
+ renderItem['arguments'][4],
+ renderItem['arguments'][5],
+ renderItem['arguments'][6],
+ renderItem['arguments'][7],
+ renderItem['arguments'][8]
+ );
+ */
+ }
+ }
+
+
+
+ break;
+ default:
+
+ }
+
+ }
+
+ }
+ /*
+ if (storageContext.clip){
+ ctx.restore();
+ }
+ */
+
+
+
+ }
+
+
+
+
+
+
+
+
+
+
+ h2clog("html2canvas: Renderer: SVG Renderer done - returning SVG DOM obj");
+
+ return svg;
+ }
+ };
+
+ return methods;
+
+
+};
\ No newline at end of file
diff --git a/src/renderers/canvas.js b/src/renderers/canvas.js
new file mode 100644
index 000000000..2ea524f5d
--- /dev/null
+++ b/src/renderers/canvas.js
@@ -0,0 +1,225 @@
+/*
+ html2canvas @VERSION@
+ Copyright (c) 2011 Niklas von Hertzen. All rights reserved.
+ http://www.twitter.com/niklasvh
+
+ Released under MIT License
+*/
+
+html2canvas.Renderer.Canvas = function( options ) {
+
+ options = options || {};
+
+ var doc = document,
+ canvas = options.canvas || doc.createElement('canvas'),
+ usingFlashcanvas = false,
+ _createCalled = false,
+ canvasReadyToDraw = false,
+ methods,
+ flashMaxSize = 2880; // flash bitmap limited to 2880x2880px // http://stackoverflow.com/questions/2033792/argumenterror-error-2015-invalid-bitmapdata
+
+
+ if (canvas.getContext){
+ html2canvas.log("html2canvas: Renderer: using canvas renderer");
+ canvasReadyToDraw = true;
+ } else if ( options.flashcanvas !== undefined ){
+ usingFlashcanvas = true;
+ html2canvas.log("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 {
+ html2canvas.log("html2canvas: Renderer: Can't track when flashcanvas is loaded");
+ }
+
+ } else {
+ return func;
+ }
+
+ })(script, function(){
+
+ if (typeof window.FlashCanvas !== "undefined") {
+ html2canvas.log("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;
+
+ 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 === "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");
+
+ queueLen = options.elements.length;
+
+ if (queueLen === 1) {
+ 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 );
+ canvas = null;
+ return newCanvas;
+ }
+ } /*else {
+ // TODO clip and resize multiple elements
+
+ for ( i = 0; i < queueLen; i+=1 ) {
+ if (options.elements[ i ] instanceof Element) {
+
+ }
+
+ }
+ }
+ */
+
+
+
+ return canvas;
+ }
+ }
+
+ return methods;
+
+};
\ No newline at end of file
diff --git a/tests/test.js b/tests/test.js
index 3fe1b1810..2e86ce4b7 100644
--- a/tests/test.js
+++ b/tests/test.js
@@ -8,7 +8,7 @@
(function(document, window) {
var scrStart = '';
document.write(scrStart + '../external/jquery-1.6.2.js' + scrEnd);
- var html2canvas = ['Core', 'Generate', 'Parse', 'Preload', 'Queue', 'Renderer', 'Util', 'plugins/jquery.plugin.html2canvas'], i;
+ var html2canvas = ['Core', 'Generate', 'Parse', 'Preload', 'Queue', 'Renderer', 'Util', 'renderers/Canvas', 'plugins/jquery.plugin.html2canvas'], i;
for (i = 0; i < html2canvas.length; ++i) {
document.write(scrStart + '../src/' + html2canvas[i] + '.js' + scrEnd);
}