@@ -10,7 +10,9 @@ html2canvas.Preload = function(element, opts){
10
10
11
11
var options = {
12
12
proxy : "http://html2canvas.appspot.com/" ,
13
- timeout : 0 // no timeout
13
+ timeout : 0 , // no timeout
14
+ useCORS : false , // try to load images as CORS (where available), before falling back to proxy
15
+ allowTaint : false // whether to allow images to taint the canvas, won't need proxy if set to true
14
16
} ,
15
17
images = {
16
18
numLoaded : 0 , // also failed are counted here
@@ -26,6 +28,9 @@ html2canvas.Preload = function(element, opts){
26
28
domImages = doc . images , // TODO probably should limit it to images present in the element only
27
29
imgLen = domImages . length ,
28
30
link = doc . createElement ( "a" ) ,
31
+ supportCORS = ( function ( img ) {
32
+ return ( img . crossOrigin !== undefined ) ;
33
+ } ) ( new Image ( ) ) ,
29
34
timeoutTimer ;
30
35
31
36
link . href = window . location . href ;
@@ -41,7 +46,7 @@ html2canvas.Preload = function(element, opts){
41
46
function isSameOrigin ( url ) {
42
47
link . href = url ;
43
48
var origin = link . protocol + link . host ;
44
- return ":" === origin || ( origin === pageOrigin ) ;
49
+ return ( origin === pageOrigin ) ;
45
50
}
46
51
47
52
function start ( ) {
@@ -215,36 +220,78 @@ html2canvas.Preload = function(element, opts){
215
220
216
221
function setImageLoadHandlers ( img , imageObj ) {
217
222
img . onload = function ( ) {
223
+ if ( imageObj . timer !== undefined ) {
224
+ // CORS succeeded
225
+ window . clearTimeout ( imageObj . timer ) ;
226
+ }
218
227
images . numLoaded ++ ;
219
228
imageObj . succeeded = true ;
220
229
start ( ) ;
221
230
} ;
222
231
img . onerror = function ( ) {
232
+
233
+ if ( img . crossOrigin === "anonymous" ) {
234
+ // CORS failed
235
+ window . clearTimeout ( imageObj . timer ) ;
236
+
237
+ // let's try with proxy instead
238
+ if ( options . proxy ) {
239
+ var src = img . src ;
240
+ img = new Image ( ) ;
241
+ imageObj . img = img ;
242
+ img . src = src ;
243
+
244
+ proxyGetImage ( img . src , img , imageObj ) ;
245
+ return ;
246
+ }
247
+ }
248
+
249
+
223
250
images . numLoaded ++ ;
224
251
images . numFailed ++ ;
225
252
imageObj . succeeded = false ;
226
253
start ( ) ;
254
+
227
255
} ;
228
256
}
257
+
258
+ // work around for https://bugs.webkit.org/show_bug.cgi?id=80028
259
+ function isComplete ( ) {
260
+ if ( ! this . img . complete ) {
261
+ this . timer = window . setTimeout ( this . img . customComplete , 100 )
262
+ } else {
263
+ this . img . onerror ( ) ;
264
+ }
265
+ }
229
266
230
267
methods = {
231
268
loadImage : function ( src ) {
232
- var img , imageObj ;
269
+ var img , imageObj ;
233
270
if ( src && images [ src ] === undefined ) {
234
- img = new Image ( ) ;
271
+ img = new Image ( ) ;
235
272
if ( src . match ( / d a t a : i m a g e \/ .* ; b a s e 6 4 , / i) ) {
236
273
img . src = src . replace ( / u r l \( [ ' " ] { 0 , } | [ ' " ] { 0 , } \) $ / ig, '' ) ;
237
274
imageObj = images [ src ] = { img : img } ;
238
275
images . numTotal ++ ;
239
276
setImageLoadHandlers ( img , imageObj ) ;
240
- }
241
- else if ( isSameOrigin ( src ) ) {
277
+ } else if ( isSameOrigin ( src ) || options . allowTaint === true ) {
242
278
imageObj = images [ src ] = { img : img } ;
243
279
images . numTotal ++ ;
244
280
setImageLoadHandlers ( img , imageObj ) ;
245
281
img . src = src ;
246
- }
247
- else if ( options . proxy ) {
282
+ } else if ( supportCORS && ! options . allowTaint && options . useCORS ) {
283
+ // attempt to load with CORS
284
+
285
+ img . crossOrigin = "anonymous" ;
286
+ imageObj = images [ src ] = { img : img } ;
287
+ images . numTotal ++ ;
288
+ setImageLoadHandlers ( img , imageObj ) ;
289
+ img . src = src ;
290
+
291
+ img . customComplete = isComplete . bind ( imageObj ) ;
292
+ img . customComplete ( ) ;
293
+
294
+ } else if ( options . proxy ) {
248
295
imageObj = images [ src ] = { img : img } ;
249
296
images . numTotal ++ ;
250
297
proxyGetImage ( src , img , imageObj ) ;
0 commit comments