@@ -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" :
0 commit comments