Skip to content

Commit

Permalink
added support for CORS images and option to create canvas as tainted
Browse files Browse the repository at this point in the history
  • Loading branch information
niklasvh committed Mar 1, 2012
1 parent c86d12b commit 3ad49ef
Show file tree
Hide file tree
Showing 5 changed files with 65 additions and 33 deletions.
2 changes: 1 addition & 1 deletion readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ For more information and examples, please visit the <a href="http://html2canvas.
### Changelog ###

v0.33 -

* Added support for CORS images and option to create canvas as tainted (<a href="#">niklasvh</a>)
* Improved minification saved ~1K! (<a href="https://github.com/cobexer/html2canvas/commit/b82be022b2b9240bd503e078ac980bde2b953e43">cobexer</a>)
* Added integrated support for Flashcanvas (<a href="https://github.com/niklasvh/html2canvas/commit/e9257191519f67d74fd5e364d8dee3c0963ba5fc">niklasvh</a>)
* Fixed a variety of legacy IE bugs (<a href="https://github.com/niklasvh/html2canvas/commit/b65357c55d0701017bafcd357bc654b54d458f8f">niklasvh</a>)
Expand Down
63 changes: 55 additions & 8 deletions src/Preload.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,9 @@ html2canvas.Preload = function(element, opts){

var options = {
proxy: "http://html2canvas.appspot.com/",
timeout: 0 // no timeout
timeout: 0, // no timeout
useCORS: false, // try to load images as CORS (where available), before falling back to proxy
allowTaint: false // whether to allow images to taint the canvas, won't need proxy if set to true
},
images = {
numLoaded: 0, // also failed are counted here
Expand All @@ -26,6 +28,9 @@ html2canvas.Preload = function(element, opts){
domImages = doc.images, // TODO probably should limit it to images present in the element only
imgLen = domImages.length,
link = doc.createElement("a"),
supportCORS = (function( img ){
return (img.crossOrigin !== undefined);
})(new Image()),
timeoutTimer;

link.href = window.location.href;
Expand All @@ -41,7 +46,7 @@ html2canvas.Preload = function(element, opts){
function isSameOrigin(url){
link.href = url;
var origin = link.protocol + link.host;
return ":" === origin || (origin === pageOrigin);
return (origin === pageOrigin);
}

function start(){
Expand Down Expand Up @@ -215,36 +220,78 @@ html2canvas.Preload = function(element, opts){

function setImageLoadHandlers(img, imageObj) {
img.onload = function() {
if ( imageObj.timer !== undefined ) {
// CORS succeeded
window.clearTimeout( imageObj.timer );
}
images.numLoaded++;
imageObj.succeeded = true;
start();
};
img.onerror = function() {

if (img.crossOrigin === "anonymous") {
// CORS failed
window.clearTimeout( imageObj.timer );

// let's try with proxy instead
if ( options.proxy ) {
var src = img.src;
img = new Image();
imageObj.img = img;
img.src = src;

proxyGetImage( img.src, img, imageObj );
return;
}
}


images.numLoaded++;
images.numFailed++;
imageObj.succeeded = false;
start();

};
}

// work around for https://bugs.webkit.org/show_bug.cgi?id=80028
function isComplete() {
if (!this.img.complete) {
this.timer = window.setTimeout(this.img.customComplete, 100)
} else {
this.img.onerror();
}
}

methods = {
loadImage: function( src ) {
var img, imageObj;
var img, imageObj;
if ( src && images[src] === undefined ) {
img = new Image();
img = new Image();
if ( src.match(/data:image\/.*;base64,/i) ) {
img.src = src.replace(/url\(['"]{0,}|['"]{0,}\)$/ig, '');
imageObj = images[src] = { img: img };
images.numTotal++;
setImageLoadHandlers(img, imageObj);
}
else if ( isSameOrigin( src ) ) {
} else if ( isSameOrigin( src ) || options.allowTaint === true ) {
imageObj = images[src] = { img: img };
images.numTotal++;
setImageLoadHandlers(img, imageObj);
img.src = src;
}
else if ( options.proxy ) {
} else if ( supportCORS && !options.allowTaint && options.useCORS ) {
// attempt to load with CORS

img.crossOrigin = "anonymous";
imageObj = images[src] = { img: img };
images.numTotal++;
setImageLoadHandlers(img, imageObj);
img.src = src;

img.customComplete = isComplete.bind(imageObj);
img.customComplete();

} else if ( options.proxy ) {
imageObj = images[src] = { img: img };
images.numTotal++;
proxyGetImage( src, img, imageObj );
Expand Down
25 changes: 3 additions & 22 deletions src/Renderer.js
Original file line number Diff line number Diff line change
Expand Up @@ -127,35 +127,16 @@ html2canvas.Renderer = function(parseQueue, opts){
if (renderItem.name === "fillRect") {

if (!usingFlashcanvas || renderItem['arguments'][0] + renderItem['arguments'][2] < flashMaxSize && renderItem['arguments'][1] + renderItem['arguments'][3] < flashMaxSize) {
ctx.fillRect(
renderItem['arguments'][0],
renderItem['arguments'][1],
renderItem['arguments'][2],
renderItem['arguments'][3]
);
ctx.fillRect.apply( ctx, renderItem['arguments'] );
}
}else if(renderItem.name === "fillText") {
if (!usingFlashcanvas || renderItem['arguments'][1] < flashMaxSize && renderItem['arguments'][2] < flashMaxSize) {
ctx.fillText(
renderItem['arguments'][0],
renderItem['arguments'][1],
renderItem['arguments'][2]
);
ctx.fillText.apply( ctx, renderItem['arguments'] );
}
}else if(renderItem.name === "drawImage") {

if (renderItem['arguments'][8] > 0 && renderItem['arguments'][7]){
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]
);
ctx.drawImage.apply( ctx, renderItem['arguments'] );
}
}

Expand Down
5 changes: 4 additions & 1 deletion tests/proxy.html
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<script type="text/javascript" src="test.js"></script>

<base href="http://www.google.com/" />
<base href="http://www.google.com/" />
</head>
<body>
<h1>External image</h1>
Expand All @@ -14,5 +14,8 @@ <h1>External image</h1>
<h1>External image (using &lt;base&gt; href)</h1>
<img src="/logos/2011/gregormendel11-res.jpg" />

<h1>External image (CORS)</h1>
<img src="http://publishmydata.com/assets/home/blue_bg.png" />

</body>
</html>
3 changes: 2 additions & 1 deletion tests/test.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,8 @@
setTimeout(function() {
$(document.body).html2canvas({
logging: true,
profile: true
profile: true,
useCORS: true
});
}, 100);
};
Expand Down

0 comments on commit 3ad49ef

Please # to comment.