From 36052c2765c4ed5a59955db7aa56c7ae312c83b2 Mon Sep 17 00:00:00 2001 From: Niklas von Hertzen Date: Mon, 8 Sep 2014 23:44:10 +0300 Subject: [PATCH] Add support for inline, base64 and node svg's --- .jshintrc | 2 +- dist/html2canvas.js | 114 ++++++++++++++++++++++------- dist/html2canvas.min.js | 4 +- src/imageloader.js | 37 ++++++++-- src/nodecontainer.js | 4 +- src/nodeparser.js | 9 ++- src/svgcontainer.js | 50 +++++++++---- src/svgnodecontainer.js | 13 ++++ tests/cases/images/svg/base64.html | 13 ++++ tests/cases/images/svg/inline.html | 14 ++++ tests/cases/images/svg/node.html | 20 +++++ tests/test.js | 2 +- 12 files changed, 226 insertions(+), 56 deletions(-) create mode 100644 src/svgnodecontainer.js create mode 100644 tests/cases/images/svg/base64.html create mode 100644 tests/cases/images/svg/inline.html create mode 100644 tests/cases/images/svg/node.html diff --git a/.jshintrc b/.jshintrc index c8b810b..a5e3fed 100644 --- a/.jshintrc +++ b/.jshintrc @@ -15,5 +15,5 @@ "jQuery": true }, "predef": ["NodeParser", "NodeContainer", "StackingContext", "TextContainer", "ImageLoader", "CanvasRenderer", "Renderer", "Support", "bind", "Promise", "getBounds", "offsetBounds", "XHR", - "ImageContainer", "ProxyImageContainer", "DummyImageContainer", "Font", "FontMetrics", "GradientContainer", "LinearGradientContainer", "WebkitGradientContainer", "SVGContainer", "html2canvas", "log", "smallImage", "parseBackgrounds"] + "ImageContainer", "ProxyImageContainer", "DummyImageContainer", "Font", "FontMetrics", "GradientContainer", "LinearGradientContainer", "WebkitGradientContainer", "SVGContainer", "SVGNodeContainer", "html2canvas", "log", "smallImage", "parseBackgrounds"] } diff --git a/dist/html2canvas.js b/dist/html2canvas.js index 8b4508f..29d884c 100644 --- a/dist/html2canvas.js +++ b/dist/html2canvas.js @@ -298,6 +298,7 @@ function ImageLoader(options, support) { ImageLoader.prototype.findImages = function(nodes) { var images = []; nodes.filter(isImage).map(urlImage).forEach(this.addImage(images, this.loadImage), this); + nodes.filter(isSVGNode).map(svgImage).forEach(this.addImage(images, this.loadImage), this); return images; }; @@ -308,10 +309,12 @@ ImageLoader.prototype.findBackgroundImage = function(images, container) { ImageLoader.prototype.addImage = function(images, callback) { return function(newImage) { - if (!this.imageExists(images, newImage)) { - images.splice(0, 0, callback.apply(this, arguments)); - log('Added image #' + (images.length), newImage); - } + newImage.args.forEach(function(image) { + if (!this.imageExists(images, image)) { + images.splice(0, 0, callback.call(this, newImage)); + log('Added image #' + (images.length), image); + } + }, this); }; }; @@ -322,11 +325,11 @@ ImageLoader.prototype.hasImageBackground = function(imageData) { ImageLoader.prototype.loadImage = function(imageData) { if (imageData.method === "url") { var src = imageData.args[0]; - if (src.match(/data:image\/.*;base64,/i)) { - return new ImageContainer(src.replace(/url\(['"]{0,}|['"]{0,}\)$/ig, ''), false); - } else if (/(.+).svg$/i.test(src) && !this.support.svg && !this.options.allowTaint) { + if (this.isSVG(src) && !this.support.svg && !this.options.allowTaint) { return new SVGContainer(src); - } else if (this.isSameOrigin(src) || this.options.allowTaint === true) { + } else if (src.match(/data:image\/.*;base64,/i)) { + return new ImageContainer(src.replace(/url\(['"]{0,}|['"]{0,}\)$/ig, ''), false); + } else if (this.isSameOrigin(src) || this.options.allowTaint === true || this.isSVG(src)) { return new ImageContainer(src, false); } else if (this.support.cors && !this.options.allowTaint && this.options.useCORS) { return new ImageContainer(src, true); @@ -339,11 +342,17 @@ ImageLoader.prototype.loadImage = function(imageData) { return new LinearGradientContainer(imageData); } else if (imageData.method === "gradient") { return new WebkitGradientContainer(imageData); + } else if (imageData.method === "svg") { + return new SVGNodeContainer(imageData.args[0]); } else { return new DummyImageContainer(imageData); } }; +ImageLoader.prototype.isSVG = function(src) { + return (/(.+).svg$/i.test(src)) || SVGContainer.prototype.isInline(src); +}; + ImageLoader.prototype.imageExists = function(images, src) { return images.some(function(image) { return image.src === src; @@ -387,6 +396,10 @@ function isImage(container) { return container.node.nodeName === "IMG"; } +function isSVGNode(container) { + return container.node.nodeName === "svg"; +} + function urlImage(container) { return { args: [container.node.src], @@ -394,6 +407,14 @@ function urlImage(container) { }; } +function svgImage(container) { + return { + args: [container.node], + method: "svg" + }; +} + + function LinearGradientContainer(imageData) { GradientContainer.apply(this, arguments); this.type = this.TYPES.LINEAR; @@ -836,14 +857,14 @@ function getBounds(node) { if (node.getBoundingClientRect) { var clientRect = node.getBoundingClientRect(); var isBody = node.nodeName === "BODY"; - var width = isBody ? node.scrollWidth : node.offsetWidth; + var width = isBody ? node.scrollWidth : (node.offsetWidth == null ? clientRect.width : node.offsetWidth); return { top: clientRect.top, bottom: clientRect.bottom || (clientRect.top + clientRect.height), right: clientRect.left + width, left: clientRect.left, width: width, - height: isBody ? node.scrollHeight : node.offsetHeight + height: isBody ? node.scrollHeight : (node.offsetHeight == null ? clientRect.height : node.offsetHeight) }; } return {}; @@ -1113,8 +1134,15 @@ NodeParser.prototype.paintNode = function(container) { this.renderer.renderBackground(container, bounds, borderData.borders.map(getWidth)); }, this); this.renderer.renderBorders(borderData.borders); - switch(container.node.nodeName) { + case "svg": + var svgContainer = this.images.get(container.node); + if (svgContainer) { + this.renderer.renderImage(container, bounds, borderData, svgContainer); + } else { + log("Error loading ", container.node); + } + break; case "IMG": var imageContainer = this.images.get(container.node.src); if (imageContainer) { @@ -1750,26 +1778,60 @@ function SVGContainer(src) { this.src = src; this.image = null; var self = this; - this.promise = XHR(src).then(function(svg) { - return new Promise(function(resolve, reject) { - if (!html2canvas.fabric) { - return reject(new Error("html2canvas.svg.js is not loaded, cannot render svg")); - } - html2canvas.fabric.loadSVGFromString(svg, function (objects, options) { - var canvas = new html2canvas.fabric.StaticCanvas('c'); - self.image = canvas.lowerCanvasEl; - canvas - .setWidth(options.width) - .setHeight(options.height) - .add(html2canvas.fabric.util.groupSVGElements(objects, options)) - .renderAll(); - resolve(canvas.lowerCanvasEl); - }); + this.promise = this.hasFabric().then(function() { + return (self.isInline(src) ? Promise.resolve(self.inlineFormatting(src)) : XHR(src)); + }).then(function(svg) { + return new Promise(function(resolve) { + html2canvas.fabric.loadSVGFromString(svg, self.createCanvas.call(self, resolve)); }); }); } +SVGContainer.prototype.hasFabric = function() { + return !html2canvas.fabric ? Promise.reject(new Error("html2canvas.svg.js is not loaded, cannot render svg")) : Promise.resolve(); +}; + +SVGContainer.prototype.inlineFormatting = function(src) { + return (/^data:image\/svg\+xml;base64,/.test(src)) ? window.atob(this.removeContentType(src)) : this.removeContentType(src); +}; + +SVGContainer.prototype.removeContentType = function(src) { + return src.replace(/^data:image\/svg\+xml(;base64)?,/,''); +}; + +SVGContainer.prototype.isInline = function(src) { + return (/^data:image\/svg\+xml/i.test(src)); +}; + +SVGContainer.prototype.createCanvas = function(resolve) { + var self = this; + return function (objects, options) { + var canvas = new html2canvas.fabric.StaticCanvas('c'); + self.image = canvas.lowerCanvasEl; + canvas + .setWidth(options.width) + .setHeight(options.height) + .add(html2canvas.fabric.util.groupSVGElements(objects, options)) + .renderAll(); + resolve(canvas.lowerCanvasEl); + }; +}; + +function SVGNodeContainer(node) { + this.src = node; + this.image = null; + var self = this; + + this.promise = this.hasFabric().then(function() { + return new Promise(function(resolve) { + html2canvas.fabric.parseSVGDocument(node, self.createCanvas.call(self, resolve)); + }); + }); +} + +SVGNodeContainer.prototype = Object.create(SVGContainer.prototype); + function TextContainer(node, parent) { NodeContainer.call(this, node, parent); } diff --git a/dist/html2canvas.min.js b/dist/html2canvas.min.js index a72d1f9..b86da55 100644 --- a/dist/html2canvas.min.js +++ b/dist/html2canvas.min.js @@ -4,5 +4,5 @@ Released under MIT License */ -!function(a,b,c){function d(a,b,c,d){return i(a,c,d,b).then(function(h){u("Document cloned");var i="["+sb+"='true']";a.querySelector(i).removeAttribute(sb);var j=h.contentWindow,k=j.document.querySelector(i),l=new lb(j.document),m=new q(b,l),n=C(k),o="view"===b.type?Math.min(n.width,c):f(),p="view"===b.type?Math.min(n.height,d):g(),r=new rb(o,p,m,b),s=new E(k,r,l,m,b);return s.ready.then(function(){u("Finished rendering");var a="view"===b.type||k!==j.document.body&&k!==j.document.documentElement?e(r.canvas,n):r.canvas;return b.removeContainer&&(h.parentNode.removeChild(h),u("Cleaned up container")),a})})}function e(a,c){var d=b.createElement("canvas"),e=Math.min(a.width-1,Math.max(0,c.left)),f=Math.min(a.width,Math.max(1,c.left+c.width)),g=Math.min(a.height-1,Math.max(0,c.top)),h=Math.min(a.height,Math.max(1,c.top+c.height)),i=d.width=f-e,j=d.height=h-g;return u("Cropping canvas at:","left:",c.left,"top:",c.top,"width:",c.width,"height:",c.height),u("Resulting crop with width",i,"and height",j," with x",e,"and y",g),d.getContext("2d").drawImage(a,e,g,i,j,0,0,i,j),d}function f(){return Math.max(Math.max(b.body.scrollWidth,b.documentElement.scrollWidth),Math.max(b.body.offsetWidth,b.documentElement.offsetWidth),Math.max(b.body.clientWidth,b.documentElement.clientWidth))}function g(){return Math.max(Math.max(b.body.scrollHeight,b.documentElement.scrollHeight),Math.max(b.body.offsetHeight,b.documentElement.offsetHeight),Math.max(b.body.clientHeight,b.documentElement.clientHeight))}function h(){return"data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7"}function i(b,c,d,e){var f=b.documentElement.cloneNode(!0),g=b.createElement("iframe");return g.style.visibility="hidden",g.style.position="absolute",g.style.left=g.style.top="-10000px",g.width=c,g.height=d,g.scrolling="no",b.body.appendChild(g),new Promise(function(b){var c=g.contentWindow.document;g.contentWindow.onload=g.onload=function(){b(g)},c.open(),c.write(""),c.close(),c.replaceChild(j(c.adoptNode(f)),c.documentElement),"view"===e.type&&g.contentWindow.scrollTo(a.pageXOffset,a.pageYOffset)})}function j(a){return[].slice.call(a.childNodes,0).filter(k).forEach(function(b){"SCRIPT"===b.tagName?a.removeChild(b):j(b)}),a}function k(a){return a.nodeType===Node.ELEMENT_NODE}function l(a){if(this.src=a,u("DummyImageContainer for",a),!this.promise||!this.image){u("Initiating DummyImageContainer"),l.prototype.image=new Image;var b=this.image;l.prototype.promise=new Promise(function(a,c){b.onload=a,b.onerror=c,b.src=h(),b.complete===!0&&a(b)})}}function m(a,c){var d,e,f=b.createElement("div"),g=b.createElement("img"),i=b.createElement("span"),j="Hidden Text";f.style.visibility="hidden",f.style.fontFamily=a,f.style.fontSize=c,f.style.margin=0,f.style.padding=0,b.body.appendChild(f),g.src=h(),g.width=1,g.height=1,g.style.margin=0,g.style.padding=0,g.style.verticalAlign="baseline",i.style.fontFamily=a,i.style.fontSize=c,i.style.margin=0,i.style.padding=0,i.appendChild(b.createTextNode(j)),f.appendChild(i),f.appendChild(g),d=g.offsetTop-i.offsetTop+1,f.removeChild(i),f.appendChild(b.createTextNode(j)),f.style.lineHeight="normal",g.style.verticalAlign="super",e=g.offsetTop-f.offsetTop+1,b.body.removeChild(f),this.baseline=d,this.lineWidth=1,this.middle=e}function n(){this.data={}}function o(a){this.src=a.value,this.colorStops=[],this.type=null,this.x0=.5,this.y0=.5,this.x1=.5,this.y1=.5,this.promise=Promise.resolve(!0)}function p(a,b){this.src=a,this.image=new Image;var c=this;this.tainted=null,this.promise=new Promise(function(d,e){c.image.onload=d,c.image.onerror=e,b&&(c.image.crossOrigin="anonymous"),c.image.src=a,c.image.complete===!0&&d(c.image)})["catch"](function(){var b=new l(a);return b.promise.then(function(a){c.image=a})})}function q(b,c){this.link=null,this.options=b,this.support=c,this.origin=a.location.protocol+a.location.hostname+a.location.port}function r(a){return"IMG"===a.node.nodeName}function s(a){return{args:[a.node.src],method:"url"}}function t(a){o.apply(this,arguments),this.type=this.TYPES.LINEAR;var b=null===a.args[0].match(this.stepRegExp);b?a.args[0].split(" ").reverse().forEach(function(a){switch(a){case"left":this.x0=0,this.x1=1;break;case"top":this.y0=0,this.y1=1;break;case"right":this.x0=1,this.x1=0;break;case"bottom":this.y0=1,this.y1=0;break;case"to":var b=this.y0,c=this.x0;this.y0=this.y1,this.x0=this.x1,this.x1=c,this.y1=b;break;default:var d=a.match(this.angleRegExp);if(d)switch(d[2]){case"deg":var e=parseFloat(d[1]),f=e/(180/Math.PI),g=Math.tan(f);this.y0=2/Math.tan(g)/2,this.x0=0,this.x1=1,this.y1=0}}},this):(this.y0=0,this.y1=1),this.colorStops=a.args.slice(b?1:0).map(function(a){var b=a.match(this.stepRegExp);return{color:b[1],stop:"%"===b[3]?b[2]/100:null}},this),null===this.colorStops[0].stop&&(this.colorStops[0].stop=0),null===this.colorStops[this.colorStops.length-1].stop&&(this.colorStops[this.colorStops.length-1].stop=1),this.colorStops.forEach(function(a,b){null===a.stop&&this.colorStops.slice(b).some(function(c,d){return null!==c.stop?(a.stop=(c.stop-this.colorStops[b-1].stop)/(d+1)+this.colorStops[b-1].stop,!0):!1},this)},this)}function u(){a.html2canvas.logging&&a.console&&a.console.log&&Function.prototype.bind.call(a.console.log,a.console).apply(a.console,[Date.now()-a.html2canvas.start+"ms","html2canvas:"].concat([].slice.call(arguments,0)))}function v(a,b){this.node=a,this.parent=b,this.stack=null,this.bounds=null,this.offsetBounds=null,this.visible=null,this.computedStyles=null,this.styles={},this.backgroundImages=null,this.transformData=null,this.transformMatrix=null}function w(a){var b=a.options[a.selectedIndex||0];return b?b.text||"":""}function x(a){return a&&"matrix"===a[1]?a[2].split(",").map(function(a){return parseFloat(a.trim())}):void 0}function y(a){return-1!==a.toString().indexOf("%")}function z(a){var b,c,d,e,f,g,h,i=" \r\n ",j=[],k=0,l=0,m=function(){b&&('"'===c.substr(0,1)&&(c=c.substr(1,c.length-2)),c&&h.push(c),"-"===b.substr(0,1)&&(e=b.indexOf("-",1)+1)>0&&(d=b.substr(0,e),b=b.substr(e)),j.push({prefix:d,method:b.toLowerCase(),value:f,args:h,image:null})),h=[],b=d=c=f=""};return h=[],b=d=c=f="",a.split("").forEach(function(a){if(!(0===k&&i.indexOf(a)>-1)){switch(a){case'"':g?g===a&&(g=null):g=a;break;case"(":if(g)break;if(0===k)return k=1,void(f+=a);l++;break;case")":if(g)break;if(1===k){if(0===l)return k=0,f+=a,void m();l--}break;case",":if(g)break;if(0===k)return void m();if(1===k&&0===l&&!b.match(/^url$/i))return h.push(c),c="",void(f+=a)}f+=a,0===k?b+=a:c+=a}}),m(),j}function A(a){return a.replace("px","")}function B(a){return parseFloat(a)}function C(a){if(a.getBoundingClientRect){var b=a.getBoundingClientRect(),c="BODY"===a.nodeName,d=c?a.scrollWidth:a.offsetWidth;return{top:b.top,bottom:b.bottom||b.top+b.height,right:b.left+d,left:b.left,width:d,height:c?a.scrollHeight:a.offsetHeight}}return{}}function D(a){var b=a.offsetParent?D(a.offsetParent):{top:0,left:0};return{top:a.offsetTop+b.top,bottom:a.offsetTop+a.offsetHeight+b.top,right:a.offsetLeft+b.left+a.offsetWidth,left:a.offsetLeft+b.left,width:a.offsetWidth,height:a.offsetHeight}}function E(a,b,c,d,e){u("Starting NodeParser"),this.renderer=b,this.options=e,this.range=null,this.support=c,this.renderQueue=[],this.stack=new kb(!0,1,a.ownerDocument,null);var f=new v(a,null);a!==a.ownerDocument.documentElement&&this.renderer.isTransparent(f.css("backgroundColor"))&&b.rectangle(0,0,b.width,b.height,new v(a.ownerDocument.documentElement,null).css("backgroundColor")),f.visibile=f.isElementVisible(),this.createPseudoHideStyles(a.ownerDocument),this.nodes=gb([f].concat(this.getChildren(f)).filter(function(a){return a.visible=a.isElementVisible()}).map(this.getPseudoElements,this)),this.fontMetrics=new n,u("Fetched nodes"),this.images=d.fetch(this.nodes.filter($)),u("Creating stacking contexts"),this.createStackingContexts(),u("Sorting stacking contexts"),this.sortStackingContexts(this.stack),this.ready=this.images.ready.then(cb(function(){return u("Images loaded, starting parsing"),this.parse(this.stack),u("Render queue created with "+this.renderQueue.length+" items"),new Promise(cb(function(a){e.async?"function"==typeof e.async?e.async.call(this,this.renderQueue,a):(this.renderIndex=0,this.asyncRenderer(this.renderQueue,a)):(this.renderQueue.forEach(this.paint,this),a())},this))},this))}function F(a){return a.replace(/(\-[a-z])/g,function(a){return a.toUpperCase().replace("-","")})}function G(){}function H(a,b,c,d){var e=4*((Math.sqrt(2)-1)/3),f=c*e,g=d*e,h=a+c,i=b+d;return{topLeft:J({x:a,y:i},{x:a,y:i-g},{x:h-f,y:b},{x:h,y:b}),topRight:J({x:a,y:b},{x:a+f,y:b},{x:h,y:i-g},{x:h,y:i}),bottomRight:J({x:h,y:b},{x:h,y:b+g},{x:a+f,y:i},{x:a,y:i}),bottomLeft:J({x:h,y:i},{x:h-f,y:i},{x:a,y:b+g},{x:a,y:b})}}function I(a,b,c){var d=a.left,e=a.top,f=a.width,g=a.height,h=b[0][0],i=b[0][1],j=b[1][0],k=b[1][1],l=b[2][0],m=b[2][1],n=b[3][0],o=b[3][1],p=f-j,q=g-m,r=f-l,s=g-o;return{topLeftOuter:H(d,e,h,i).topLeft.subdivide(.5),topLeftInner:H(d+c[3].width,e+c[0].width,Math.max(0,h-c[3].width),Math.max(0,i-c[0].width)).topLeft.subdivide(.5),topRightOuter:H(d+p,e,j,k).topRight.subdivide(.5),topRightInner:H(d+Math.min(p,f+c[3].width),e+c[0].width,p>f+c[3].width?0:j-c[3].width,k-c[0].width).topRight.subdivide(.5),bottomRightOuter:H(d+r,e+q,l,m).bottomRight.subdivide(.5),bottomRightInner:H(d+Math.min(r,f+c[3].width),e+Math.min(q,g+c[0].width),Math.max(0,l-c[1].width),Math.max(0,m-c[2].width)).bottomRight.subdivide(.5),bottomLeftOuter:H(d,e+s,n,o).bottomLeft.subdivide(.5),bottomLeftInner:H(d+c[3].width,e+s,Math.max(0,n-c[3].width),Math.max(0,o-c[2].width)).bottomLeft.subdivide(.5)}}function J(a,b,c,d){var e=function(a,b,c){return{x:a.x+(b.x-a.x)*c,y:a.y+(b.y-a.y)*c}};return{start:a,startControl:b,endControl:c,end:d,subdivide:function(f){var g=e(a,b,f),h=e(b,c,f),i=e(c,d,f),j=e(g,h,f),k=e(h,i,f),l=e(j,k,f);return[J(a,g,j,l),J(l,k,i,d)]},curveTo:function(a){a.push(["bezierCurve",b.x,b.y,c.x,c.y,d.x,d.y])},curveToReversed:function(d){d.push(["bezierCurve",c.x,c.y,b.x,b.y,a.x,a.y])}}}function K(a,b,c,d,e,f,g){var h=[];return b[0]>0||b[1]>0?(h.push(["line",d[1].start.x,d[1].start.y]),d[1].curveTo(h)):h.push(["line",a.c1[0],a.c1[1]]),c[0]>0||c[1]>0?(h.push(["line",f[0].start.x,f[0].start.y]),f[0].curveTo(h),h.push(["line",g[0].end.x,g[0].end.y]),g[0].curveToReversed(h)):(h.push(["line",a.c2[0],a.c2[1]]),h.push(["line",a.c3[0],a.c3[1]])),b[0]>0||b[1]>0?(h.push(["line",e[1].end.x,e[1].end.y]),e[1].curveToReversed(h)):h.push(["line",a.c4[0],a.c4[1]]),h}function L(a,b,c,d,e,f,g){b[0]>0||b[1]>0?(a.push(["line",d[0].start.x,d[0].start.y]),d[0].curveTo(a),d[1].curveTo(a)):a.push(["line",f,g]),(c[0]>0||c[1]>0)&&a.push(["line",e[0].start.x,e[0].start.y])}function M(a){return a.cssInt("zIndex")<0}function N(a){return a.cssInt("zIndex")>0}function O(a){return 0===a.cssInt("zIndex")}function P(a){return-1!==["inline","inline-block","inline-table"].indexOf(a.css("display"))}function Q(a){return a instanceof kb}function R(a){return a.node.data.trim().length>0}function S(a){return/^(normal|none|0px)$/.test(a.parent.css("letterSpacing"))}function T(a){return["TopLeft","TopRight","BottomRight","BottomLeft"].map(function(b){var c=a.css("border"+b+"Radius"),d=c.split(" ");return d.length<=1&&(d[1]=d[0]),d.map(db)})}function U(a){return a.nodeType===Node.TEXT_NODE||a.nodeType===Node.ELEMENT_NODE}function V(a){var b=a.css("position"),c="absolute"===b||"relative"===b?a.css("zIndex"):"auto";return"auto"!==c}function W(a){return"static"!==a.css("position")}function X(a){return"none"!==a.css("float")}function Y(a){return-1!==["inline-block","inline-table"].indexOf(a.css("display"))}function Z(a){var b=this;return function(){return!a.apply(b,arguments)}}function $(a){return a.node.nodeType===Node.ELEMENT_NODE}function _(a){return a.node.nodeType===Node.TEXT_NODE}function ab(a,b){return a.cssInt("zIndex")-b.cssInt("zIndex")}function bb(a){return a.css("opacity")<1}function cb(a,b){return function(){return a.apply(b,arguments)}}function db(a){return parseInt(a,10)}function eb(a){return a.width}function fb(a){return a.node.nodeType!==Node.ELEMENT_NODE||-1===["SCRIPT","HEAD","TITLE","OBJECT","BR","OPTION"].indexOf(a.node.nodeName)}function gb(a){return[].concat.apply([],a)}function hb(a){var b=a.substr(0,1);return b===a.substr(a.length-1)&&b.match(/'|"/)?a.substr(1,a.length-2):a}function ib(d,e){var f="html2canvas_"+tb++,g=b.createElement("script"),h=b.createElement("a");h.href=d,d=h.href;var i=e+(e.indexOf("?")>-1?"&":"?")+"url="+encodeURIComponent(d)+"&callback="+f;this.src=d,this.image=new Image;var j=this;this.promise=new Promise(function(d,e){j.image.onload=d,j.image.onerror=e,a[f]=function(b){"error:"===b.substring(0,6)?e():j.image.src=b,a[f]=c;try{delete a[f]}catch(d){}g.parentNode.removeChild(g)},g.setAttribute("type","text/javascript"),g.setAttribute("src",i),b.body.appendChild(g)})["catch"](function(){var a=new l(d);return a.promise.then(function(a){j.image=a})})}function jb(a,b,c,d){this.width=a,this.height=b,this.images=c,this.options=d}function kb(a,b,c,d){v.call(this,c,d),this.ownStacking=a,this.contexts=[],this.children=[],this.opacity=(this.parent?this.parent.stack.opacity:1)*b}function lb(a){this.rangeBounds=this.testRangeBounds(a),this.cors=this.testCORS(),this.svg=this.testSVG()}function mb(a){this.src=a,this.image=null;var b=this;this.promise=qb(a).then(function(a){return new Promise(function(c,d){return html2canvas.fabric?void html2canvas.fabric.loadSVGFromString(a,function(a,d){var e=new html2canvas.fabric.StaticCanvas("c");b.image=e.lowerCanvasEl,e.setWidth(d.width).setHeight(d.height).add(html2canvas.fabric.util.groupSVGElements(a,d)).renderAll(),c(e.lowerCanvasEl)}):d(new Error("html2canvas.svg.js is not loaded, cannot render svg"))})})}function nb(a,b){v.call(this,a,b)}function ob(a,b,c){return a.length>0?b+c.toUpperCase():void 0}function pb(a){o.apply(this,arguments),this.type="linear"===a.args[0]?this.TYPES.LINEAR:this.TYPES.RADIAL}function qb(a){return new Promise(function(b,c){var d=new XMLHttpRequest;d.open("GET",a),d.onload=function(){200===d.status?b(d.responseText):c(new Error(d.statusText))},d.onerror=function(){c(new Error("Network Error"))},d.send()})}function rb(a,c){jb.apply(this,arguments),this.canvas=b.createElement("canvas"),this.canvas.width=a,this.canvas.height=c,this.ctx=this.canvas.getContext("2d"),this.taintCtx=b.createElement("canvas").getContext("2d"),this.ctx.textBaseline="bottom",this.variables={},u("Initialized CanvasRenderer")}if(!function(){var c,d,e,f;!function(){var a={},b={};c=function(b,c,d){a[b]={deps:c,callback:d}},f=e=d=function(c){function e(a){if("."!==a.charAt(0))return a;for(var b=a.split("/"),d=c.split("/").slice(0,-1),e=0,f=b.length;f>e;e++){var g=b[e];if(".."===g)d.pop();else{if("."===g)continue;d.push(g)}}return d.join("/")}if(f._eak_seen=a,b[c])return b[c];if(b[c]={},!a[c])throw new Error("Could not find module "+c);for(var g,h=a[c],i=h.deps,j=h.callback,k=[],l=0,m=i.length;m>l;l++)k.push("exports"===i[l]?g={}:d(e(i[l])));var n=j.apply(this,k);return b[c]=g||n}}(),c("promise/all",["./utils","exports"],function(a,b){"use strict";function c(a){var b=this;if(!d(a))throw new TypeError("You must pass an array to all.");return new b(function(b,c){function d(a){return function(b){f(a,b)}}function f(a,c){h[a]=c,0===--i&&b(h)}var g,h=[],i=a.length;0===i&&b([]);for(var j=0;jg^"contain"===f[0]?{width:a.height*h,height:a.height}:{width:a.width,height:a.width/h}}d=parseInt(f[0],10)}return e="auto"===f[0]&&"auto"===f[1]?b.height:"auto"===f[1]?d/b.width*b.height:y(f[1])?a.height*parseFloat(f[1])/100:parseInt(f[1],10),"auto"===f[0]&&(d=e/b.height*b.width),{width:d,height:e}},v.prototype.parseBackgroundPosition=function(a,b,c,d){var e,f,g=this.cssList("backgroundPosition",c);return e=y(g[0])?(a.width-(d||b).width)*(parseFloat(g[0])/100):parseInt(g[0],10),f="auto"===g[1]?e/b.width*b.height:y(g[1])?(a.height-(d||b).height)*parseFloat(g[1])/100:parseInt(g[1],10),"auto"===g[0]&&(e=f/b.height*b.width),{left:e,top:f}},v.prototype.parseBackgroundRepeat=function(a){return this.cssList("backgroundRepeat",a)[0]},v.prototype.parseTextShadows=function(){var a=this.css("textShadow"),b=[];if(a&&"none"!==a)for(var c=a.match(this.TEXT_SHADOW_PROPERTY),d=0;c&&dDate.now()?this.asyncRenderer(a,b,c):setTimeout(cb(function(){this.asyncRenderer(a,b)},this),0)},E.prototype.createPseudoHideStyles=function(a){var b=a.createElement("style");b.innerHTML="."+this.pseudoHideClass+':before { content: "" !important; display: none !important; }.'+this.pseudoHideClass+':after { content: "" !important; display: none !important; }',a.body.appendChild(b)},E.prototype.getPseudoElements=function(a){var b=[[a]];if(a.node.nodeType===Node.ELEMENT_NODE){var c=this.getPseudoElement(a,":before"),d=this.getPseudoElement(a,":after");c&&(a.node.insertBefore(c[0].node,a.node.firstChild),b.push(c)),d&&(a.node.appendChild(d[0].node),b.push(d)),(c||d)&&(a.node.className+=" "+this.pseudoHideClass)}return gb(b)},E.prototype.getPseudoElement=function(a,c){var d=a.computedStyle(c);if(!d||!d.content||"none"===d.content||"-moz-alt-content"===d.content||"none"===d.display)return null;for(var e=hb(d.content),f="url"===e.substr(0,3),g=b.createElement(f?"img":"html2canvaspseudoelement"),h=new v(g,a),i=d.length-1;i>=0;i--){var j=F(d.item(i));g.style[j]=d[j]}if(g.className=this.pseudoHideClass,f)return g.src=z(e)[0].args[0],[h];var k=b.createTextNode(e);return g.appendChild(k),[h,new nb(k,h)]},E.prototype.getChildren=function(a){return gb([].filter.call(a.node.childNodes,U).map(function(b){var c=[b.nodeType===Node.TEXT_NODE?new nb(b,a):new v(b,a)].filter(fb);return b.nodeType===Node.ELEMENT_NODE&&c.length&&"TEXTAREA"!==b.tagName?c[0].isElementVisible()?c.concat(this.getChildren(c[0])):[]:c},this))},E.prototype.newStackingContext=function(a,b){var c=new kb(b,a.cssFloat("opacity"),a.node,a.parent);c.visible=a.visible;var d=b?c.getParentStack(this):c.parent.stack;d.contexts.push(c),a.stack=c},E.prototype.createStackingContexts=function(){this.nodes.forEach(function(a){$(a)&&(this.isRootElement(a)||bb(a)||V(a)||this.isBodyWithTransparentRoot(a)||a.hasTransform())?this.newStackingContext(a,!0):$(a)&&(W(a)&&O(a)||Y(a)||X(a))?this.newStackingContext(a,!1):a.assignStack(a.parent.stack)},this)},E.prototype.isBodyWithTransparentRoot=function(a){return"BODY"===a.node.nodeName&&this.renderer.isTransparent(a.parent.css("backgroundColor"))},E.prototype.isRootElement=function(a){return null===a.parent},E.prototype.sortStackingContexts=function(a){a.contexts.sort(ab),a.contexts.forEach(this.sortStackingContexts,this)},E.prototype.parseTextBounds=function(a){return function(b,c,d){if("none"!==a.parent.css("textDecoration").substr(0,4)||0!==b.trim().length){if(this.support.rangeBounds&&!a.parent.hasTransform()){var e=d.slice(0,c).join("").length;return this.getRangeBounds(a.node,e,b.length)}if(a.node&&"string"==typeof a.node.data){var f=a.node.splitText(b.length),g=this.getWrapperBounds(a.node,a.parent.hasTransform());return a.node=f,g}}else(!this.support.rangeBounds||a.parent.hasTransform())&&(a.node=a.node.splitText(b.length));return{}}},E.prototype.getWrapperBounds=function(a,b){var c=a.ownerDocument.createElement("html2canvaswrapper"),d=a.parentNode,e=a.cloneNode(!0);c.appendChild(a.cloneNode(!0)),d.replaceChild(c,a);var f=b?D(c):C(c);return d.replaceChild(e,c),f},E.prototype.getRangeBounds=function(a,b,c){var d=this.range||(this.range=a.ownerDocument.createRange());return d.setStart(a,b),d.setEnd(a,b+c),d.getBoundingClientRect()},E.prototype.parse=function(a){var b=a.contexts.filter(M),c=a.children.filter($),d=c.filter(Z(X)),e=d.filter(Z(W)).filter(Z(P)),f=c.filter(Z(W)).filter(X),g=d.filter(Z(W)).filter(P),h=a.contexts.concat(d.filter(W)).filter(O),i=a.children.filter(_).filter(R),j=a.contexts.filter(N);b.concat(e).concat(f).concat(g).concat(h).concat(i).concat(j).forEach(function(a){this.renderQueue.push(a),Q(a)&&(this.parse(a),this.renderQueue.push(new G))},this)},E.prototype.paint=function(a){try{a instanceof G?this.renderer.ctx.restore():_(a)?this.paintText(a):this.paintNode(a)}catch(b){u(b)}},E.prototype.paintNode=function(a){Q(a)&&(this.renderer.setOpacity(a.opacity),this.renderer.ctx.save(),a.hasTransform()&&this.renderer.setTransform(a.parseTransform()));var b=a.parseBounds(),c=this.parseBorders(a);switch(this.renderer.clip(c.clip,function(){this.renderer.renderBackground(a,b,c.borders.map(eb))},this),this.renderer.renderBorders(c.borders),a.node.nodeName){case"IMG":var d=this.images.get(a.node.src);d?this.renderer.renderImage(a,b,c,d):u("Error loading ",a.node.src);break;case"SELECT":case"INPUT":case"TEXTAREA":this.paintFormValue(a)}},E.prototype.paintFormValue=function(a){if(a.getValue().length>0){var b=a.node.ownerDocument,c=b.createElement("html2canvaswrapper"),d=["lineHeight","textAlign","fontFamily","fontWeight","fontSize","color","paddingLeft","paddingTop","paddingRight","paddingBottom","width","height","borderLeftStyle","borderTopStyle","borderLeftWidth","borderTopWidth","boxSizing","whiteSpace","wordWrap"];d.forEach(function(b){try{c.style[b]=a.css(b)}catch(d){u("html2canvas: Parse: Exception caught in renderFormValue: "+d.message)}});var e=a.parseBounds();c.style.position="absolute",c.style.left=e.left+"px",c.style.top=e.top+"px",c.textContent=a.getValue(),b.body.appendChild(c),this.paintText(new nb(c.firstChild,a)),b.body.removeChild(c)}},E.prototype.paintText=function(a){a.applyTextTransform();var b=a.node.data.split(!this.options.letterRendering||S(a)?/(\b| )/:""),c=a.parent.fontWeight(),d=a.parent.css("fontSize"),e=a.parent.css("fontFamily"),f=a.parent.parseTextShadows(); -this.renderer.font(a.parent.css("color"),a.parent.css("fontStyle"),a.parent.css("fontVariant"),c,d,e),f.length?this.renderer.fontShadow(f[0].color,f[0].offsetX,f[0].offsetY,f[0].blur):this.renderer.clearShadow(),b.map(this.parseTextBounds(a),this).forEach(function(c,f){c&&(this.renderer.text(b[f],c.left,c.bottom),this.renderTextDecoration(a.parent,c,this.fontMetrics.getMetrics(e,d)))},this)},E.prototype.renderTextDecoration=function(a,b,c){switch(a.css("textDecoration").split(" ")[0]){case"underline":this.renderer.rectangle(b.left,Math.round(b.top+c.baseline+c.lineWidth),b.width,1,a.css("color"));break;case"overline":this.renderer.rectangle(b.left,Math.round(b.top),b.width,1,a.css("color"));break;case"line-through":this.renderer.rectangle(b.left,Math.ceil(b.top+c.middle+c.lineWidth),b.width,1,a.css("color"))}},E.prototype.parseBorders=function(a){var b=a.bounds,c=T(a),d=["Top","Right","Bottom","Left"].map(function(b){return{width:a.cssInt("border"+b+"Width"),color:a.css("border"+b+"Color"),args:null}}),e=I(b,c,d);return{clip:this.parseBackgroundClip(a,e,d,c,b),borders:d.map(function(a,f){if(a.width>0){var g=b.left,h=b.top,i=b.width,j=b.height-d[2].width;switch(f){case 0:j=d[0].width,a.args=K({c1:[g,h],c2:[g+i,h],c3:[g+i-d[1].width,h+j],c4:[g+d[3].width,h+j]},c[0],c[1],e.topLeftOuter,e.topLeftInner,e.topRightOuter,e.topRightInner);break;case 1:g=b.left+b.width-d[1].width,i=d[1].width,a.args=K({c1:[g+i,h],c2:[g+i,h+j+d[2].width],c3:[g,h+j],c4:[g,h+d[0].width]},c[1],c[2],e.topRightOuter,e.topRightInner,e.bottomRightOuter,e.bottomRightInner);break;case 2:h=h+b.height-d[2].width,j=d[2].width,a.args=K({c1:[g+i,h+j],c2:[g,h+j],c3:[g+d[3].width,h],c4:[g+i-d[3].width,h]},c[2],c[3],e.bottomRightOuter,e.bottomRightInner,e.bottomLeftOuter,e.bottomLeftInner);break;case 3:i=d[3].width,a.args=K({c1:[g,h+j+d[2].width],c2:[g,h],c3:[g+i,h+d[0].width],c4:[g+i,h+j]},c[3],c[0],e.bottomLeftOuter,e.bottomLeftInner,e.topLeftOuter,e.topLeftInner)}}return a})}},E.prototype.parseBackgroundClip=function(a,b,c,d,e){var f=a.css("backgroundClip"),g=[];switch(f){case"content-box":case"padding-box":L(g,d[0],d[1],b.topLeftInner,b.topRightInner,e.left+c[3].width,e.top+c[0].width),L(g,d[1],d[2],b.topRightInner,b.bottomRightInner,e.left+e.width-c[1].width,e.top+c[0].width),L(g,d[2],d[3],b.bottomRightInner,b.bottomLeftInner,e.left+e.width-c[1].width,e.top+e.height-c[2].width),L(g,d[3],d[0],b.bottomLeftInner,b.topLeftInner,e.left+c[3].width,e.top+e.height-c[2].width);break;default:L(g,d[0],d[1],b.topLeftOuter,b.topRightOuter,e.left,e.top),L(g,d[1],d[2],b.topRightOuter,b.bottomRightOuter,e.left+e.width,e.top),L(g,d[2],d[3],b.bottomRightOuter,b.bottomLeftOuter,e.left+e.width,e.top+e.height),L(g,d[3],d[0],b.bottomLeftOuter,b.topLeftOuter,e.left,e.top+e.height)}return g},E.prototype.pseudoHideClass="___html2canvas___pseudoelement";var tb=0;jb.prototype.renderImage=function(a,b,c,d){var e=a.cssInt("paddingLeft"),f=a.cssInt("paddingTop"),g=a.cssInt("paddingRight"),h=a.cssInt("paddingBottom"),i=c.borders,j=b.width-(i[1].width+i[3].width+e+g),k=b.height-(i[0].width+i[2].width+f+h);this.drawImage(d,0,0,d.image.width||j,d.image.height||k,b.left+e+i[3].width,b.top+f+i[0].width,j,k)},jb.prototype.renderBackground=function(a,b,c){b.height>0&&b.width>0&&(this.renderBackgroundColor(a,b),this.renderBackgroundImage(a,b,c))},jb.prototype.renderBackgroundColor=function(a,b){var c=a.css("backgroundColor");this.isTransparent(c)||this.rectangle(b.left,b.top,b.width,b.height,a.css("backgroundColor"))},jb.prototype.renderBorders=function(a){a.forEach(this.renderBorder,this)},jb.prototype.renderBorder=function(a){this.isTransparent(a.color)||null===a.args||this.drawShape(a.args,a.color)},jb.prototype.renderBackgroundImage=function(a,b,c){var d=a.parseBackgroundImages();d.reverse().forEach(function(d,e,f){switch(d.method){case"url":var g=this.images.get(d.args[0]);g?this.renderBackgroundRepeating(a,b,g,f.length-(e+1),c):u("Error loading background-image",d.args[0]);break;case"linear-gradient":case"gradient":var h=this.images.get(d.value);h?this.renderBackgroundGradient(h,b,c):u("Error loading background-image",d.args[0]);break;case"none":break;default:u("Unknown background-image type",d.args[0])}},this)},jb.prototype.renderBackgroundRepeating=function(a,b,c,d,e){var f=a.parseBackgroundSize(b,c.image,d),g=a.parseBackgroundPosition(b,c.image,d,f),h=a.parseBackgroundRepeat(d);switch(h){case"repeat-x":case"repeat no-repeat":this.backgroundRepeatShape(c,g,f,b,b.left+e[3],b.top+g.top+e[0],99999,c.image.height,e);break;case"repeat-y":case"no-repeat repeat":this.backgroundRepeatShape(c,g,f,b,b.left+g.left+e[3],b.top+e[0],c.image.width,99999,e);break;case"no-repeat":this.backgroundRepeatShape(c,g,f,b,b.left+g.left+e[3],b.top+g.top+e[0],c.image.width,c.image.height,e);break;default:this.renderBackgroundRepeat(c,g,f,{top:b.top,left:b.left},e[3],e[0])}},jb.prototype.isTransparent=function(a){return!a||"transparent"===a||"rgba(0, 0, 0, 0)"===a},kb.prototype=Object.create(v.prototype),kb.prototype.getParentStack=function(a){var b=this.parent?this.parent.stack:null;return b?b.ownStacking?b:b.getParentStack(a):a.stack},lb.prototype.testRangeBounds=function(a){var b,c,d,e,f=!1;return a.createRange&&(b=a.createRange(),b.getBoundingClientRect&&(c=a.createElement("boundtest"),c.style.height="123px",c.style.display="block",a.body.appendChild(c),b.selectNode(c),d=b.getBoundingClientRect(),e=d.height,123===e&&(f=!0),a.body.removeChild(c))),f},lb.prototype.testCORS=function(){return"undefined"!=typeof(new Image).crossOrigin},lb.prototype.testSVG=function(){var a=new Image,c=b.createElement("canvas"),d=c.getContext("2d");a.src="data:image/svg+xml,";try{d.drawImage(a,0,0),c.toDataURL()}catch(e){return!1}return!0},nb.prototype=Object.create(v.prototype),nb.prototype.applyTextTransform=function(){this.node.data=this.transform(this.parent.css("textTransform"))},nb.prototype.transform=function(a){var b=this.node.data;switch(a){case"lowercase":return b.toLowerCase();case"capitalize":return b.replace(/(^|\s|:|-|\(|\))([a-z])/g,ob);case"uppercase":return b.toUpperCase();default:return b}},pb.prototype=Object.create(o.prototype),rb.prototype=Object.create(jb.prototype),rb.prototype.setFillStyle=function(a){return this.ctx.fillStyle=a,this.ctx},rb.prototype.rectangle=function(a,b,c,d,e){this.setFillStyle(e).fillRect(a,b,c,d)},rb.prototype.drawShape=function(a,b){this.shape(a),this.setFillStyle(b).fill()},rb.prototype.taints=function(a){if(null===a.tainted){this.taintCtx.drawImage(a.image,0,0);try{this.taintCtx.getImageData(0,0,1,1),a.tainted=!1}catch(c){this.taintCtx=b.createElement("canvas").getContext("2d"),a.tainted=!0}}return a.tainted},rb.prototype.drawImage=function(a,b,c,d,e,f,g,h,i){(!this.taints(a)||this.options.allowTaint)&&this.ctx.drawImage(a.image,b,c,d,e,f,g,h,i)},rb.prototype.clip=function(a,b,c){this.ctx.save(),this.shape(a).clip(),b.call(c),this.ctx.restore()},rb.prototype.shape=function(a){return this.ctx.beginPath(),a.forEach(function(a,b){this.ctx[0===b?"moveTo":a[0]+"To"].apply(this.ctx,a.slice(1))},this),this.ctx.closePath(),this.ctx},rb.prototype.font=function(a,b,c,d,e,f){this.setFillStyle(a).font=[b,c,d,e,f].join(" ")},rb.prototype.fontShadow=function(a,b,c,d){this.setVariable("shadowColor",a).setVariable("shadowOffsetY",b).setVariable("shadowOffsetX",c).setVariable("shadowBlur",d)},rb.prototype.clearShadow=function(){this.setVariable("shadowColor","rgba(0,0,0,0)")},rb.prototype.setOpacity=function(a){this.ctx.globalAlpha=a},rb.prototype.setTransform=function(a){this.ctx.translate(a.origin[0],a.origin[1]),this.ctx.transform.apply(this.ctx,a.matrix),this.ctx.translate(-a.origin[0],-a.origin[1])},rb.prototype.setVariable=function(a,b){return this.variables[a]!==b&&(this.variables[a]=this.ctx[a]=b),this},rb.prototype.text=function(a,b,c){this.ctx.fillText(a,b,c)},rb.prototype.backgroundRepeatShape=function(a,b,c,d,e,f,g,h,i){var j=[["line",Math.round(e),Math.round(f)],["line",Math.round(e+g),Math.round(f)],["line",Math.round(e+g),Math.round(h+f)],["line",Math.round(e),Math.round(h+f)]];this.clip(j,function(){this.renderBackgroundRepeat(a,b,c,d,i[3],i[0])},this)},rb.prototype.renderBackgroundRepeat=function(a,b,c,d,e,f){var g=Math.round(d.left+b.left+e),h=Math.round(d.top+b.top+f);this.setFillStyle(this.ctx.createPattern(this.resizeImage(a,c),"repeat")),this.ctx.translate(g,h),this.ctx.fill(),this.ctx.translate(-g,-h)},rb.prototype.renderBackgroundGradient=function(a,b){if(a instanceof t){var c=this.ctx.createLinearGradient(b.left+b.width*a.x0,b.top+b.height*a.y0,b.left+b.width*a.x1,b.top+b.height*a.y1);a.colorStops.forEach(function(a){c.addColorStop(a.stop,a.color)}),this.rectangle(b.left,b.top,b.width,b.height,c)}},rb.prototype.resizeImage=function(a,c){var d=a.image;if(d.width===c.width&&d.height===c.height)return d;var e,f=b.createElement("canvas");return f.width=c.width,f.height=c.height,e=f.getContext("2d"),e.drawImage(d,0,0,d.width,d.height,0,0,c.width,c.height),f}}(window,document); \ No newline at end of file +!function(a,b,c){function d(a,b,c,d){return i(a,c,d,b).then(function(h){w("Document cloned");var i="["+vb+"='true']";a.querySelector(i).removeAttribute(vb);var j=h.contentWindow,k=j.document.querySelector(i),l=new nb(j.document),m=new q(b,l),n=E(k),o="view"===b.type?Math.min(n.width,c):f(),p="view"===b.type?Math.min(n.height,d):g(),r=new ub(o,p,m,b),s=new G(k,r,l,m,b);return s.ready.then(function(){w("Finished rendering");var a="view"===b.type||k!==j.document.body&&k!==j.document.documentElement?e(r.canvas,n):r.canvas;return b.removeContainer&&(h.parentNode.removeChild(h),w("Cleaned up container")),a})})}function e(a,c){var d=b.createElement("canvas"),e=Math.min(a.width-1,Math.max(0,c.left)),f=Math.min(a.width,Math.max(1,c.left+c.width)),g=Math.min(a.height-1,Math.max(0,c.top)),h=Math.min(a.height,Math.max(1,c.top+c.height)),i=d.width=f-e,j=d.height=h-g;return w("Cropping canvas at:","left:",c.left,"top:",c.top,"width:",c.width,"height:",c.height),w("Resulting crop with width",i,"and height",j," with x",e,"and y",g),d.getContext("2d").drawImage(a,e,g,i,j,0,0,i,j),d}function f(){return Math.max(Math.max(b.body.scrollWidth,b.documentElement.scrollWidth),Math.max(b.body.offsetWidth,b.documentElement.offsetWidth),Math.max(b.body.clientWidth,b.documentElement.clientWidth))}function g(){return Math.max(Math.max(b.body.scrollHeight,b.documentElement.scrollHeight),Math.max(b.body.offsetHeight,b.documentElement.offsetHeight),Math.max(b.body.clientHeight,b.documentElement.clientHeight))}function h(){return"data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7"}function i(b,c,d,e){var f=b.documentElement.cloneNode(!0),g=b.createElement("iframe");return g.style.visibility="hidden",g.style.position="absolute",g.style.left=g.style.top="-10000px",g.width=c,g.height=d,g.scrolling="no",b.body.appendChild(g),new Promise(function(b){var c=g.contentWindow.document;g.contentWindow.onload=g.onload=function(){b(g)},c.open(),c.write(""),c.close(),c.replaceChild(j(c.adoptNode(f)),c.documentElement),"view"===e.type&&g.contentWindow.scrollTo(a.pageXOffset,a.pageYOffset)})}function j(a){return[].slice.call(a.childNodes,0).filter(k).forEach(function(b){"SCRIPT"===b.tagName?a.removeChild(b):j(b)}),a}function k(a){return a.nodeType===Node.ELEMENT_NODE}function l(a){if(this.src=a,w("DummyImageContainer for",a),!this.promise||!this.image){w("Initiating DummyImageContainer"),l.prototype.image=new Image;var b=this.image;l.prototype.promise=new Promise(function(a,c){b.onload=a,b.onerror=c,b.src=h(),b.complete===!0&&a(b)})}}function m(a,c){var d,e,f=b.createElement("div"),g=b.createElement("img"),i=b.createElement("span"),j="Hidden Text";f.style.visibility="hidden",f.style.fontFamily=a,f.style.fontSize=c,f.style.margin=0,f.style.padding=0,b.body.appendChild(f),g.src=h(),g.width=1,g.height=1,g.style.margin=0,g.style.padding=0,g.style.verticalAlign="baseline",i.style.fontFamily=a,i.style.fontSize=c,i.style.margin=0,i.style.padding=0,i.appendChild(b.createTextNode(j)),f.appendChild(i),f.appendChild(g),d=g.offsetTop-i.offsetTop+1,f.removeChild(i),f.appendChild(b.createTextNode(j)),f.style.lineHeight="normal",g.style.verticalAlign="super",e=g.offsetTop-f.offsetTop+1,b.body.removeChild(f),this.baseline=d,this.lineWidth=1,this.middle=e}function n(){this.data={}}function o(a){this.src=a.value,this.colorStops=[],this.type=null,this.x0=.5,this.y0=.5,this.x1=.5,this.y1=.5,this.promise=Promise.resolve(!0)}function p(a,b){this.src=a,this.image=new Image;var c=this;this.tainted=null,this.promise=new Promise(function(d,e){c.image.onload=d,c.image.onerror=e,b&&(c.image.crossOrigin="anonymous"),c.image.src=a,c.image.complete===!0&&d(c.image)})["catch"](function(){var b=new l(a);return b.promise.then(function(a){c.image=a})})}function q(b,c){this.link=null,this.options=b,this.support=c,this.origin=a.location.protocol+a.location.hostname+a.location.port}function r(a){return"IMG"===a.node.nodeName}function s(a){return"svg"===a.node.nodeName}function t(a){return{args:[a.node.src],method:"url"}}function u(a){return{args:[a.node],method:"svg"}}function v(a){o.apply(this,arguments),this.type=this.TYPES.LINEAR;var b=null===a.args[0].match(this.stepRegExp);b?a.args[0].split(" ").reverse().forEach(function(a){switch(a){case"left":this.x0=0,this.x1=1;break;case"top":this.y0=0,this.y1=1;break;case"right":this.x0=1,this.x1=0;break;case"bottom":this.y0=1,this.y1=0;break;case"to":var b=this.y0,c=this.x0;this.y0=this.y1,this.x0=this.x1,this.x1=c,this.y1=b;break;default:var d=a.match(this.angleRegExp);if(d)switch(d[2]){case"deg":var e=parseFloat(d[1]),f=e/(180/Math.PI),g=Math.tan(f);this.y0=2/Math.tan(g)/2,this.x0=0,this.x1=1,this.y1=0}}},this):(this.y0=0,this.y1=1),this.colorStops=a.args.slice(b?1:0).map(function(a){var b=a.match(this.stepRegExp);return{color:b[1],stop:"%"===b[3]?b[2]/100:null}},this),null===this.colorStops[0].stop&&(this.colorStops[0].stop=0),null===this.colorStops[this.colorStops.length-1].stop&&(this.colorStops[this.colorStops.length-1].stop=1),this.colorStops.forEach(function(a,b){null===a.stop&&this.colorStops.slice(b).some(function(c,d){return null!==c.stop?(a.stop=(c.stop-this.colorStops[b-1].stop)/(d+1)+this.colorStops[b-1].stop,!0):!1},this)},this)}function w(){a.html2canvas.logging&&a.console&&a.console.log&&Function.prototype.bind.call(a.console.log,a.console).apply(a.console,[Date.now()-a.html2canvas.start+"ms","html2canvas:"].concat([].slice.call(arguments,0)))}function x(a,b){this.node=a,this.parent=b,this.stack=null,this.bounds=null,this.offsetBounds=null,this.visible=null,this.computedStyles=null,this.styles={},this.backgroundImages=null,this.transformData=null,this.transformMatrix=null}function y(a){var b=a.options[a.selectedIndex||0];return b?b.text||"":""}function z(a){return a&&"matrix"===a[1]?a[2].split(",").map(function(a){return parseFloat(a.trim())}):void 0}function A(a){return-1!==a.toString().indexOf("%")}function B(a){var b,c,d,e,f,g,h,i=" \r\n ",j=[],k=0,l=0,m=function(){b&&('"'===c.substr(0,1)&&(c=c.substr(1,c.length-2)),c&&h.push(c),"-"===b.substr(0,1)&&(e=b.indexOf("-",1)+1)>0&&(d=b.substr(0,e),b=b.substr(e)),j.push({prefix:d,method:b.toLowerCase(),value:f,args:h,image:null})),h=[],b=d=c=f=""};return h=[],b=d=c=f="",a.split("").forEach(function(a){if(!(0===k&&i.indexOf(a)>-1)){switch(a){case'"':g?g===a&&(g=null):g=a;break;case"(":if(g)break;if(0===k)return k=1,void(f+=a);l++;break;case")":if(g)break;if(1===k){if(0===l)return k=0,f+=a,void m();l--}break;case",":if(g)break;if(0===k)return void m();if(1===k&&0===l&&!b.match(/^url$/i))return h.push(c),c="",void(f+=a)}f+=a,0===k?b+=a:c+=a}}),m(),j}function C(a){return a.replace("px","")}function D(a){return parseFloat(a)}function E(a){if(a.getBoundingClientRect){var b=a.getBoundingClientRect(),c="BODY"===a.nodeName,d=c?a.scrollWidth:null==a.offsetWidth?b.width:a.offsetWidth;return{top:b.top,bottom:b.bottom||b.top+b.height,right:b.left+d,left:b.left,width:d,height:c?a.scrollHeight:null==a.offsetHeight?b.height:a.offsetHeight}}return{}}function F(a){var b=a.offsetParent?F(a.offsetParent):{top:0,left:0};return{top:a.offsetTop+b.top,bottom:a.offsetTop+a.offsetHeight+b.top,right:a.offsetLeft+b.left+a.offsetWidth,left:a.offsetLeft+b.left,width:a.offsetWidth,height:a.offsetHeight}}function G(a,b,c,d,e){w("Starting NodeParser"),this.renderer=b,this.options=e,this.range=null,this.support=c,this.renderQueue=[],this.stack=new mb(!0,1,a.ownerDocument,null);var f=new x(a,null);a!==a.ownerDocument.documentElement&&this.renderer.isTransparent(f.css("backgroundColor"))&&b.rectangle(0,0,b.width,b.height,new x(a.ownerDocument.documentElement,null).css("backgroundColor")),f.visibile=f.isElementVisible(),this.createPseudoHideStyles(a.ownerDocument),this.nodes=ib([f].concat(this.getChildren(f)).filter(function(a){return a.visible=a.isElementVisible()}).map(this.getPseudoElements,this)),this.fontMetrics=new n,w("Fetched nodes"),this.images=d.fetch(this.nodes.filter(ab)),w("Creating stacking contexts"),this.createStackingContexts(),w("Sorting stacking contexts"),this.sortStackingContexts(this.stack),this.ready=this.images.ready.then(eb(function(){return w("Images loaded, starting parsing"),this.parse(this.stack),w("Render queue created with "+this.renderQueue.length+" items"),new Promise(eb(function(a){e.async?"function"==typeof e.async?e.async.call(this,this.renderQueue,a):(this.renderIndex=0,this.asyncRenderer(this.renderQueue,a)):(this.renderQueue.forEach(this.paint,this),a())},this))},this))}function H(a){return a.replace(/(\-[a-z])/g,function(a){return a.toUpperCase().replace("-","")})}function I(){}function J(a,b,c,d){var e=4*((Math.sqrt(2)-1)/3),f=c*e,g=d*e,h=a+c,i=b+d;return{topLeft:L({x:a,y:i},{x:a,y:i-g},{x:h-f,y:b},{x:h,y:b}),topRight:L({x:a,y:b},{x:a+f,y:b},{x:h,y:i-g},{x:h,y:i}),bottomRight:L({x:h,y:b},{x:h,y:b+g},{x:a+f,y:i},{x:a,y:i}),bottomLeft:L({x:h,y:i},{x:h-f,y:i},{x:a,y:b+g},{x:a,y:b})}}function K(a,b,c){var d=a.left,e=a.top,f=a.width,g=a.height,h=b[0][0],i=b[0][1],j=b[1][0],k=b[1][1],l=b[2][0],m=b[2][1],n=b[3][0],o=b[3][1],p=f-j,q=g-m,r=f-l,s=g-o;return{topLeftOuter:J(d,e,h,i).topLeft.subdivide(.5),topLeftInner:J(d+c[3].width,e+c[0].width,Math.max(0,h-c[3].width),Math.max(0,i-c[0].width)).topLeft.subdivide(.5),topRightOuter:J(d+p,e,j,k).topRight.subdivide(.5),topRightInner:J(d+Math.min(p,f+c[3].width),e+c[0].width,p>f+c[3].width?0:j-c[3].width,k-c[0].width).topRight.subdivide(.5),bottomRightOuter:J(d+r,e+q,l,m).bottomRight.subdivide(.5),bottomRightInner:J(d+Math.min(r,f+c[3].width),e+Math.min(q,g+c[0].width),Math.max(0,l-c[1].width),Math.max(0,m-c[2].width)).bottomRight.subdivide(.5),bottomLeftOuter:J(d,e+s,n,o).bottomLeft.subdivide(.5),bottomLeftInner:J(d+c[3].width,e+s,Math.max(0,n-c[3].width),Math.max(0,o-c[2].width)).bottomLeft.subdivide(.5)}}function L(a,b,c,d){var e=function(a,b,c){return{x:a.x+(b.x-a.x)*c,y:a.y+(b.y-a.y)*c}};return{start:a,startControl:b,endControl:c,end:d,subdivide:function(f){var g=e(a,b,f),h=e(b,c,f),i=e(c,d,f),j=e(g,h,f),k=e(h,i,f),l=e(j,k,f);return[L(a,g,j,l),L(l,k,i,d)]},curveTo:function(a){a.push(["bezierCurve",b.x,b.y,c.x,c.y,d.x,d.y])},curveToReversed:function(d){d.push(["bezierCurve",c.x,c.y,b.x,b.y,a.x,a.y])}}}function M(a,b,c,d,e,f,g){var h=[];return b[0]>0||b[1]>0?(h.push(["line",d[1].start.x,d[1].start.y]),d[1].curveTo(h)):h.push(["line",a.c1[0],a.c1[1]]),c[0]>0||c[1]>0?(h.push(["line",f[0].start.x,f[0].start.y]),f[0].curveTo(h),h.push(["line",g[0].end.x,g[0].end.y]),g[0].curveToReversed(h)):(h.push(["line",a.c2[0],a.c2[1]]),h.push(["line",a.c3[0],a.c3[1]])),b[0]>0||b[1]>0?(h.push(["line",e[1].end.x,e[1].end.y]),e[1].curveToReversed(h)):h.push(["line",a.c4[0],a.c4[1]]),h}function N(a,b,c,d,e,f,g){b[0]>0||b[1]>0?(a.push(["line",d[0].start.x,d[0].start.y]),d[0].curveTo(a),d[1].curveTo(a)):a.push(["line",f,g]),(c[0]>0||c[1]>0)&&a.push(["line",e[0].start.x,e[0].start.y])}function O(a){return a.cssInt("zIndex")<0}function P(a){return a.cssInt("zIndex")>0}function Q(a){return 0===a.cssInt("zIndex")}function R(a){return-1!==["inline","inline-block","inline-table"].indexOf(a.css("display"))}function S(a){return a instanceof mb}function T(a){return a.node.data.trim().length>0}function U(a){return/^(normal|none|0px)$/.test(a.parent.css("letterSpacing"))}function V(a){return["TopLeft","TopRight","BottomRight","BottomLeft"].map(function(b){var c=a.css("border"+b+"Radius"),d=c.split(" ");return d.length<=1&&(d[1]=d[0]),d.map(fb)})}function W(a){return a.nodeType===Node.TEXT_NODE||a.nodeType===Node.ELEMENT_NODE}function X(a){var b=a.css("position"),c="absolute"===b||"relative"===b?a.css("zIndex"):"auto";return"auto"!==c}function Y(a){return"static"!==a.css("position")}function Z(a){return"none"!==a.css("float")}function $(a){return-1!==["inline-block","inline-table"].indexOf(a.css("display"))}function _(a){var b=this;return function(){return!a.apply(b,arguments)}}function ab(a){return a.node.nodeType===Node.ELEMENT_NODE}function bb(a){return a.node.nodeType===Node.TEXT_NODE}function cb(a,b){return a.cssInt("zIndex")-b.cssInt("zIndex")}function db(a){return a.css("opacity")<1}function eb(a,b){return function(){return a.apply(b,arguments)}}function fb(a){return parseInt(a,10)}function gb(a){return a.width}function hb(a){return a.node.nodeType!==Node.ELEMENT_NODE||-1===["SCRIPT","HEAD","TITLE","OBJECT","BR","OPTION"].indexOf(a.node.nodeName)}function ib(a){return[].concat.apply([],a)}function jb(a){var b=a.substr(0,1);return b===a.substr(a.length-1)&&b.match(/'|"/)?a.substr(1,a.length-2):a}function kb(d,e){var f="html2canvas_"+wb++,g=b.createElement("script"),h=b.createElement("a");h.href=d,d=h.href;var i=e+(e.indexOf("?")>-1?"&":"?")+"url="+encodeURIComponent(d)+"&callback="+f;this.src=d,this.image=new Image;var j=this;this.promise=new Promise(function(d,e){j.image.onload=d,j.image.onerror=e,a[f]=function(b){"error:"===b.substring(0,6)?e():j.image.src=b,a[f]=c;try{delete a[f]}catch(d){}g.parentNode.removeChild(g)},g.setAttribute("type","text/javascript"),g.setAttribute("src",i),b.body.appendChild(g)})["catch"](function(){var a=new l(d);return a.promise.then(function(a){j.image=a})})}function lb(a,b,c,d){this.width=a,this.height=b,this.images=c,this.options=d}function mb(a,b,c,d){x.call(this,c,d),this.ownStacking=a,this.contexts=[],this.children=[],this.opacity=(this.parent?this.parent.stack.opacity:1)*b}function nb(a){this.rangeBounds=this.testRangeBounds(a),this.cors=this.testCORS(),this.svg=this.testSVG()}function ob(a){this.src=a,this.image=null;var b=this;this.promise=this.hasFabric().then(function(){return b.isInline(a)?Promise.resolve(b.inlineFormatting(a)):tb(a)}).then(function(a){return new Promise(function(c){html2canvas.fabric.loadSVGFromString(a,b.createCanvas.call(b,c))})})}function pb(a){this.src=a,this.image=null;var b=this;this.promise=this.hasFabric().then(function(){return new Promise(function(c){html2canvas.fabric.parseSVGDocument(a,b.createCanvas.call(b,c))})})}function qb(a,b){x.call(this,a,b)}function rb(a,b,c){return a.length>0?b+c.toUpperCase():void 0}function sb(a){o.apply(this,arguments),this.type="linear"===a.args[0]?this.TYPES.LINEAR:this.TYPES.RADIAL}function tb(a){return new Promise(function(b,c){var d=new XMLHttpRequest;d.open("GET",a),d.onload=function(){200===d.status?b(d.responseText):c(new Error(d.statusText))},d.onerror=function(){c(new Error("Network Error"))},d.send()})}function ub(a,c){lb.apply(this,arguments),this.canvas=b.createElement("canvas"),this.canvas.width=a,this.canvas.height=c,this.ctx=this.canvas.getContext("2d"),this.taintCtx=b.createElement("canvas").getContext("2d"),this.ctx.textBaseline="bottom",this.variables={},w("Initialized CanvasRenderer")}if(!function(){var c,d,e,f;!function(){var a={},b={};c=function(b,c,d){a[b]={deps:c,callback:d}},f=e=d=function(c){function e(a){if("."!==a.charAt(0))return a;for(var b=a.split("/"),d=c.split("/").slice(0,-1),e=0,f=b.length;f>e;e++){var g=b[e];if(".."===g)d.pop();else{if("."===g)continue;d.push(g)}}return d.join("/")}if(f._eak_seen=a,b[c])return b[c];if(b[c]={},!a[c])throw new Error("Could not find module "+c);for(var g,h=a[c],i=h.deps,j=h.callback,k=[],l=0,m=i.length;m>l;l++)k.push("exports"===i[l]?g={}:d(e(i[l])));var n=j.apply(this,k);return b[c]=g||n}}(),c("promise/all",["./utils","exports"],function(a,b){"use strict";function c(a){var b=this;if(!d(a))throw new TypeError("You must pass an array to all.");return new b(function(b,c){function d(a){return function(b){f(a,b)}}function f(a,c){h[a]=c,0===--i&&b(h)}var g,h=[],i=a.length;0===i&&b([]);for(var j=0;jg^"contain"===f[0]?{width:a.height*h,height:a.height}:{width:a.width,height:a.width/h}}d=parseInt(f[0],10)}return e="auto"===f[0]&&"auto"===f[1]?b.height:"auto"===f[1]?d/b.width*b.height:A(f[1])?a.height*parseFloat(f[1])/100:parseInt(f[1],10),"auto"===f[0]&&(d=e/b.height*b.width),{width:d,height:e}},x.prototype.parseBackgroundPosition=function(a,b,c,d){var e,f,g=this.cssList("backgroundPosition",c);return e=A(g[0])?(a.width-(d||b).width)*(parseFloat(g[0])/100):parseInt(g[0],10),f="auto"===g[1]?e/b.width*b.height:A(g[1])?(a.height-(d||b).height)*parseFloat(g[1])/100:parseInt(g[1],10),"auto"===g[0]&&(e=f/b.height*b.width),{left:e,top:f}},x.prototype.parseBackgroundRepeat=function(a){return this.cssList("backgroundRepeat",a)[0]},x.prototype.parseTextShadows=function(){var a=this.css("textShadow"),b=[];if(a&&"none"!==a)for(var c=a.match(this.TEXT_SHADOW_PROPERTY),d=0;c&&dDate.now()?this.asyncRenderer(a,b,c):setTimeout(eb(function(){this.asyncRenderer(a,b)},this),0)},G.prototype.createPseudoHideStyles=function(a){var b=a.createElement("style");b.innerHTML="."+this.pseudoHideClass+':before { content: "" !important; display: none !important; }.'+this.pseudoHideClass+':after { content: "" !important; display: none !important; }',a.body.appendChild(b)},G.prototype.getPseudoElements=function(a){var b=[[a]];if(a.node.nodeType===Node.ELEMENT_NODE){var c=this.getPseudoElement(a,":before"),d=this.getPseudoElement(a,":after");c&&(a.node.insertBefore(c[0].node,a.node.firstChild),b.push(c)),d&&(a.node.appendChild(d[0].node),b.push(d)),(c||d)&&(a.node.className+=" "+this.pseudoHideClass)}return ib(b)},G.prototype.getPseudoElement=function(a,c){var d=a.computedStyle(c);if(!d||!d.content||"none"===d.content||"-moz-alt-content"===d.content||"none"===d.display)return null;for(var e=jb(d.content),f="url"===e.substr(0,3),g=b.createElement(f?"img":"html2canvaspseudoelement"),h=new x(g,a),i=d.length-1;i>=0;i--){var j=H(d.item(i));g.style[j]=d[j]}if(g.className=this.pseudoHideClass,f)return g.src=B(e)[0].args[0],[h];var k=b.createTextNode(e);return g.appendChild(k),[h,new qb(k,h)]},G.prototype.getChildren=function(a){return ib([].filter.call(a.node.childNodes,W).map(function(b){var c=[b.nodeType===Node.TEXT_NODE?new qb(b,a):new x(b,a)].filter(hb);return b.nodeType===Node.ELEMENT_NODE&&c.length&&"TEXTAREA"!==b.tagName?c[0].isElementVisible()?c.concat(this.getChildren(c[0])):[]:c},this))},G.prototype.newStackingContext=function(a,b){var c=new mb(b,a.cssFloat("opacity"),a.node,a.parent);c.visible=a.visible;var d=b?c.getParentStack(this):c.parent.stack;d.contexts.push(c),a.stack=c},G.prototype.createStackingContexts=function(){this.nodes.forEach(function(a){ab(a)&&(this.isRootElement(a)||db(a)||X(a)||this.isBodyWithTransparentRoot(a)||a.hasTransform())?this.newStackingContext(a,!0):ab(a)&&(Y(a)&&Q(a)||$(a)||Z(a))?this.newStackingContext(a,!1):a.assignStack(a.parent.stack)},this)},G.prototype.isBodyWithTransparentRoot=function(a){return"BODY"===a.node.nodeName&&this.renderer.isTransparent(a.parent.css("backgroundColor"))},G.prototype.isRootElement=function(a){return null===a.parent},G.prototype.sortStackingContexts=function(a){a.contexts.sort(cb),a.contexts.forEach(this.sortStackingContexts,this)},G.prototype.parseTextBounds=function(a){return function(b,c,d){if("none"!==a.parent.css("textDecoration").substr(0,4)||0!==b.trim().length){if(this.support.rangeBounds&&!a.parent.hasTransform()){var e=d.slice(0,c).join("").length;return this.getRangeBounds(a.node,e,b.length)}if(a.node&&"string"==typeof a.node.data){var f=a.node.splitText(b.length),g=this.getWrapperBounds(a.node,a.parent.hasTransform());return a.node=f,g}}else(!this.support.rangeBounds||a.parent.hasTransform())&&(a.node=a.node.splitText(b.length));return{}}},G.prototype.getWrapperBounds=function(a,b){var c=a.ownerDocument.createElement("html2canvaswrapper"),d=a.parentNode,e=a.cloneNode(!0);c.appendChild(a.cloneNode(!0)),d.replaceChild(c,a);var f=b?F(c):E(c);return d.replaceChild(e,c),f},G.prototype.getRangeBounds=function(a,b,c){var d=this.range||(this.range=a.ownerDocument.createRange());return d.setStart(a,b),d.setEnd(a,b+c),d.getBoundingClientRect()},G.prototype.parse=function(a){var b=a.contexts.filter(O),c=a.children.filter(ab),d=c.filter(_(Z)),e=d.filter(_(Y)).filter(_(R)),f=c.filter(_(Y)).filter(Z),g=d.filter(_(Y)).filter(R),h=a.contexts.concat(d.filter(Y)).filter(Q),i=a.children.filter(bb).filter(T),j=a.contexts.filter(P);b.concat(e).concat(f).concat(g).concat(h).concat(i).concat(j).forEach(function(a){this.renderQueue.push(a),S(a)&&(this.parse(a),this.renderQueue.push(new I))},this)},G.prototype.paint=function(a){try{a instanceof I?this.renderer.ctx.restore():bb(a)?this.paintText(a):this.paintNode(a)}catch(b){w(b)}},G.prototype.paintNode=function(a){S(a)&&(this.renderer.setOpacity(a.opacity),this.renderer.ctx.save(),a.hasTransform()&&this.renderer.setTransform(a.parseTransform()));var b=a.parseBounds(),c=this.parseBorders(a);switch(this.renderer.clip(c.clip,function(){this.renderer.renderBackground(a,b,c.borders.map(gb))},this),this.renderer.renderBorders(c.borders),a.node.nodeName){case"svg":var d=this.images.get(a.node);d?this.renderer.renderImage(a,b,c,d):w("Error loading ",a.node);break;case"IMG":var e=this.images.get(a.node.src);e?this.renderer.renderImage(a,b,c,e):w("Error loading ",a.node.src);break;case"SELECT":case"INPUT":case"TEXTAREA":this.paintFormValue(a)}},G.prototype.paintFormValue=function(a){if(a.getValue().length>0){var b=a.node.ownerDocument,c=b.createElement("html2canvaswrapper"),d=["lineHeight","textAlign","fontFamily","fontWeight","fontSize","color","paddingLeft","paddingTop","paddingRight","paddingBottom","width","height","borderLeftStyle","borderTopStyle","borderLeftWidth","borderTopWidth","boxSizing","whiteSpace","wordWrap"];d.forEach(function(b){try{c.style[b]=a.css(b)}catch(d){w("html2canvas: Parse: Exception caught in renderFormValue: "+d.message) +}});var e=a.parseBounds();c.style.position="absolute",c.style.left=e.left+"px",c.style.top=e.top+"px",c.textContent=a.getValue(),b.body.appendChild(c),this.paintText(new qb(c.firstChild,a)),b.body.removeChild(c)}},G.prototype.paintText=function(a){a.applyTextTransform();var b=a.node.data.split(!this.options.letterRendering||U(a)?/(\b| )/:""),c=a.parent.fontWeight(),d=a.parent.css("fontSize"),e=a.parent.css("fontFamily"),f=a.parent.parseTextShadows();this.renderer.font(a.parent.css("color"),a.parent.css("fontStyle"),a.parent.css("fontVariant"),c,d,e),f.length?this.renderer.fontShadow(f[0].color,f[0].offsetX,f[0].offsetY,f[0].blur):this.renderer.clearShadow(),b.map(this.parseTextBounds(a),this).forEach(function(c,f){c&&(this.renderer.text(b[f],c.left,c.bottom),this.renderTextDecoration(a.parent,c,this.fontMetrics.getMetrics(e,d)))},this)},G.prototype.renderTextDecoration=function(a,b,c){switch(a.css("textDecoration").split(" ")[0]){case"underline":this.renderer.rectangle(b.left,Math.round(b.top+c.baseline+c.lineWidth),b.width,1,a.css("color"));break;case"overline":this.renderer.rectangle(b.left,Math.round(b.top),b.width,1,a.css("color"));break;case"line-through":this.renderer.rectangle(b.left,Math.ceil(b.top+c.middle+c.lineWidth),b.width,1,a.css("color"))}},G.prototype.parseBorders=function(a){var b=a.bounds,c=V(a),d=["Top","Right","Bottom","Left"].map(function(b){return{width:a.cssInt("border"+b+"Width"),color:a.css("border"+b+"Color"),args:null}}),e=K(b,c,d);return{clip:this.parseBackgroundClip(a,e,d,c,b),borders:d.map(function(a,f){if(a.width>0){var g=b.left,h=b.top,i=b.width,j=b.height-d[2].width;switch(f){case 0:j=d[0].width,a.args=M({c1:[g,h],c2:[g+i,h],c3:[g+i-d[1].width,h+j],c4:[g+d[3].width,h+j]},c[0],c[1],e.topLeftOuter,e.topLeftInner,e.topRightOuter,e.topRightInner);break;case 1:g=b.left+b.width-d[1].width,i=d[1].width,a.args=M({c1:[g+i,h],c2:[g+i,h+j+d[2].width],c3:[g,h+j],c4:[g,h+d[0].width]},c[1],c[2],e.topRightOuter,e.topRightInner,e.bottomRightOuter,e.bottomRightInner);break;case 2:h=h+b.height-d[2].width,j=d[2].width,a.args=M({c1:[g+i,h+j],c2:[g,h+j],c3:[g+d[3].width,h],c4:[g+i-d[3].width,h]},c[2],c[3],e.bottomRightOuter,e.bottomRightInner,e.bottomLeftOuter,e.bottomLeftInner);break;case 3:i=d[3].width,a.args=M({c1:[g,h+j+d[2].width],c2:[g,h],c3:[g+i,h+d[0].width],c4:[g+i,h+j]},c[3],c[0],e.bottomLeftOuter,e.bottomLeftInner,e.topLeftOuter,e.topLeftInner)}}return a})}},G.prototype.parseBackgroundClip=function(a,b,c,d,e){var f=a.css("backgroundClip"),g=[];switch(f){case"content-box":case"padding-box":N(g,d[0],d[1],b.topLeftInner,b.topRightInner,e.left+c[3].width,e.top+c[0].width),N(g,d[1],d[2],b.topRightInner,b.bottomRightInner,e.left+e.width-c[1].width,e.top+c[0].width),N(g,d[2],d[3],b.bottomRightInner,b.bottomLeftInner,e.left+e.width-c[1].width,e.top+e.height-c[2].width),N(g,d[3],d[0],b.bottomLeftInner,b.topLeftInner,e.left+c[3].width,e.top+e.height-c[2].width);break;default:N(g,d[0],d[1],b.topLeftOuter,b.topRightOuter,e.left,e.top),N(g,d[1],d[2],b.topRightOuter,b.bottomRightOuter,e.left+e.width,e.top),N(g,d[2],d[3],b.bottomRightOuter,b.bottomLeftOuter,e.left+e.width,e.top+e.height),N(g,d[3],d[0],b.bottomLeftOuter,b.topLeftOuter,e.left,e.top+e.height)}return g},G.prototype.pseudoHideClass="___html2canvas___pseudoelement";var wb=0;lb.prototype.renderImage=function(a,b,c,d){var e=a.cssInt("paddingLeft"),f=a.cssInt("paddingTop"),g=a.cssInt("paddingRight"),h=a.cssInt("paddingBottom"),i=c.borders,j=b.width-(i[1].width+i[3].width+e+g),k=b.height-(i[0].width+i[2].width+f+h);this.drawImage(d,0,0,d.image.width||j,d.image.height||k,b.left+e+i[3].width,b.top+f+i[0].width,j,k)},lb.prototype.renderBackground=function(a,b,c){b.height>0&&b.width>0&&(this.renderBackgroundColor(a,b),this.renderBackgroundImage(a,b,c))},lb.prototype.renderBackgroundColor=function(a,b){var c=a.css("backgroundColor");this.isTransparent(c)||this.rectangle(b.left,b.top,b.width,b.height,a.css("backgroundColor"))},lb.prototype.renderBorders=function(a){a.forEach(this.renderBorder,this)},lb.prototype.renderBorder=function(a){this.isTransparent(a.color)||null===a.args||this.drawShape(a.args,a.color)},lb.prototype.renderBackgroundImage=function(a,b,c){var d=a.parseBackgroundImages();d.reverse().forEach(function(d,e,f){switch(d.method){case"url":var g=this.images.get(d.args[0]);g?this.renderBackgroundRepeating(a,b,g,f.length-(e+1),c):w("Error loading background-image",d.args[0]);break;case"linear-gradient":case"gradient":var h=this.images.get(d.value);h?this.renderBackgroundGradient(h,b,c):w("Error loading background-image",d.args[0]);break;case"none":break;default:w("Unknown background-image type",d.args[0])}},this)},lb.prototype.renderBackgroundRepeating=function(a,b,c,d,e){var f=a.parseBackgroundSize(b,c.image,d),g=a.parseBackgroundPosition(b,c.image,d,f),h=a.parseBackgroundRepeat(d);switch(h){case"repeat-x":case"repeat no-repeat":this.backgroundRepeatShape(c,g,f,b,b.left+e[3],b.top+g.top+e[0],99999,c.image.height,e);break;case"repeat-y":case"no-repeat repeat":this.backgroundRepeatShape(c,g,f,b,b.left+g.left+e[3],b.top+e[0],c.image.width,99999,e);break;case"no-repeat":this.backgroundRepeatShape(c,g,f,b,b.left+g.left+e[3],b.top+g.top+e[0],c.image.width,c.image.height,e);break;default:this.renderBackgroundRepeat(c,g,f,{top:b.top,left:b.left},e[3],e[0])}},lb.prototype.isTransparent=function(a){return!a||"transparent"===a||"rgba(0, 0, 0, 0)"===a},mb.prototype=Object.create(x.prototype),mb.prototype.getParentStack=function(a){var b=this.parent?this.parent.stack:null;return b?b.ownStacking?b:b.getParentStack(a):a.stack},nb.prototype.testRangeBounds=function(a){var b,c,d,e,f=!1;return a.createRange&&(b=a.createRange(),b.getBoundingClientRect&&(c=a.createElement("boundtest"),c.style.height="123px",c.style.display="block",a.body.appendChild(c),b.selectNode(c),d=b.getBoundingClientRect(),e=d.height,123===e&&(f=!0),a.body.removeChild(c))),f},nb.prototype.testCORS=function(){return"undefined"!=typeof(new Image).crossOrigin},nb.prototype.testSVG=function(){var a=new Image,c=b.createElement("canvas"),d=c.getContext("2d");a.src="data:image/svg+xml,";try{d.drawImage(a,0,0),c.toDataURL()}catch(e){return!1}return!0},ob.prototype.hasFabric=function(){return html2canvas.fabric?Promise.resolve():Promise.reject(new Error("html2canvas.svg.js is not loaded, cannot render svg"))},ob.prototype.inlineFormatting=function(b){return/^data:image\/svg\+xml;base64,/.test(b)?a.atob(this.removeContentType(b)):this.removeContentType(b)},ob.prototype.removeContentType=function(a){return a.replace(/^data:image\/svg\+xml(;base64)?,/,"")},ob.prototype.isInline=function(a){return/^data:image\/svg\+xml/i.test(a)},ob.prototype.createCanvas=function(a){var b=this;return function(c,d){var e=new html2canvas.fabric.StaticCanvas("c");b.image=e.lowerCanvasEl,e.setWidth(d.width).setHeight(d.height).add(html2canvas.fabric.util.groupSVGElements(c,d)).renderAll(),a(e.lowerCanvasEl)}},pb.prototype=Object.create(ob.prototype),qb.prototype=Object.create(x.prototype),qb.prototype.applyTextTransform=function(){this.node.data=this.transform(this.parent.css("textTransform"))},qb.prototype.transform=function(a){var b=this.node.data;switch(a){case"lowercase":return b.toLowerCase();case"capitalize":return b.replace(/(^|\s|:|-|\(|\))([a-z])/g,rb);case"uppercase":return b.toUpperCase();default:return b}},sb.prototype=Object.create(o.prototype),ub.prototype=Object.create(lb.prototype),ub.prototype.setFillStyle=function(a){return this.ctx.fillStyle=a,this.ctx},ub.prototype.rectangle=function(a,b,c,d,e){this.setFillStyle(e).fillRect(a,b,c,d)},ub.prototype.drawShape=function(a,b){this.shape(a),this.setFillStyle(b).fill()},ub.prototype.taints=function(a){if(null===a.tainted){this.taintCtx.drawImage(a.image,0,0);try{this.taintCtx.getImageData(0,0,1,1),a.tainted=!1}catch(c){this.taintCtx=b.createElement("canvas").getContext("2d"),a.tainted=!0}}return a.tainted},ub.prototype.drawImage=function(a,b,c,d,e,f,g,h,i){(!this.taints(a)||this.options.allowTaint)&&this.ctx.drawImage(a.image,b,c,d,e,f,g,h,i)},ub.prototype.clip=function(a,b,c){this.ctx.save(),this.shape(a).clip(),b.call(c),this.ctx.restore()},ub.prototype.shape=function(a){return this.ctx.beginPath(),a.forEach(function(a,b){this.ctx[0===b?"moveTo":a[0]+"To"].apply(this.ctx,a.slice(1))},this),this.ctx.closePath(),this.ctx},ub.prototype.font=function(a,b,c,d,e,f){this.setFillStyle(a).font=[b,c,d,e,f].join(" ")},ub.prototype.fontShadow=function(a,b,c,d){this.setVariable("shadowColor",a).setVariable("shadowOffsetY",b).setVariable("shadowOffsetX",c).setVariable("shadowBlur",d)},ub.prototype.clearShadow=function(){this.setVariable("shadowColor","rgba(0,0,0,0)")},ub.prototype.setOpacity=function(a){this.ctx.globalAlpha=a},ub.prototype.setTransform=function(a){this.ctx.translate(a.origin[0],a.origin[1]),this.ctx.transform.apply(this.ctx,a.matrix),this.ctx.translate(-a.origin[0],-a.origin[1])},ub.prototype.setVariable=function(a,b){return this.variables[a]!==b&&(this.variables[a]=this.ctx[a]=b),this},ub.prototype.text=function(a,b,c){this.ctx.fillText(a,b,c)},ub.prototype.backgroundRepeatShape=function(a,b,c,d,e,f,g,h,i){var j=[["line",Math.round(e),Math.round(f)],["line",Math.round(e+g),Math.round(f)],["line",Math.round(e+g),Math.round(h+f)],["line",Math.round(e),Math.round(h+f)]];this.clip(j,function(){this.renderBackgroundRepeat(a,b,c,d,i[3],i[0])},this)},ub.prototype.renderBackgroundRepeat=function(a,b,c,d,e,f){var g=Math.round(d.left+b.left+e),h=Math.round(d.top+b.top+f);this.setFillStyle(this.ctx.createPattern(this.resizeImage(a,c),"repeat")),this.ctx.translate(g,h),this.ctx.fill(),this.ctx.translate(-g,-h)},ub.prototype.renderBackgroundGradient=function(a,b){if(a instanceof v){var c=this.ctx.createLinearGradient(b.left+b.width*a.x0,b.top+b.height*a.y0,b.left+b.width*a.x1,b.top+b.height*a.y1);a.colorStops.forEach(function(a){c.addColorStop(a.stop,a.color)}),this.rectangle(b.left,b.top,b.width,b.height,c)}},ub.prototype.resizeImage=function(a,c){var d=a.image;if(d.width===c.width&&d.height===c.height)return d;var e,f=b.createElement("canvas");return f.width=c.width,f.height=c.height,e=f.getContext("2d"),e.drawImage(d,0,0,d.width,d.height,0,0,c.width,c.height),f}}(window,document); \ No newline at end of file diff --git a/src/imageloader.js b/src/imageloader.js index 9f41250..5387c71 100644 --- a/src/imageloader.js +++ b/src/imageloader.js @@ -8,6 +8,7 @@ function ImageLoader(options, support) { ImageLoader.prototype.findImages = function(nodes) { var images = []; nodes.filter(isImage).map(urlImage).forEach(this.addImage(images, this.loadImage), this); + nodes.filter(isSVGNode).map(svgImage).forEach(this.addImage(images, this.loadImage), this); return images; }; @@ -18,10 +19,12 @@ ImageLoader.prototype.findBackgroundImage = function(images, container) { ImageLoader.prototype.addImage = function(images, callback) { return function(newImage) { - if (!this.imageExists(images, newImage)) { - images.splice(0, 0, callback.apply(this, arguments)); - log('Added image #' + (images.length), newImage); - } + newImage.args.forEach(function(image) { + if (!this.imageExists(images, image)) { + images.splice(0, 0, callback.call(this, newImage)); + log('Added image #' + (images.length), image); + } + }, this); }; }; @@ -32,11 +35,11 @@ ImageLoader.prototype.hasImageBackground = function(imageData) { ImageLoader.prototype.loadImage = function(imageData) { if (imageData.method === "url") { var src = imageData.args[0]; - if (src.match(/data:image\/.*;base64,/i)) { - return new ImageContainer(src.replace(/url\(['"]{0,}|['"]{0,}\)$/ig, ''), false); - } else if (/(.+).svg$/i.test(src) && !this.support.svg && !this.options.allowTaint) { + if (this.isSVG(src) && !this.support.svg && !this.options.allowTaint) { return new SVGContainer(src); - } else if (this.isSameOrigin(src) || this.options.allowTaint === true) { + } else if (src.match(/data:image\/.*;base64,/i)) { + return new ImageContainer(src.replace(/url\(['"]{0,}|['"]{0,}\)$/ig, ''), false); + } else if (this.isSameOrigin(src) || this.options.allowTaint === true || this.isSVG(src)) { return new ImageContainer(src, false); } else if (this.support.cors && !this.options.allowTaint && this.options.useCORS) { return new ImageContainer(src, true); @@ -49,11 +52,17 @@ ImageLoader.prototype.loadImage = function(imageData) { return new LinearGradientContainer(imageData); } else if (imageData.method === "gradient") { return new WebkitGradientContainer(imageData); + } else if (imageData.method === "svg") { + return new SVGNodeContainer(imageData.args[0]); } else { return new DummyImageContainer(imageData); } }; +ImageLoader.prototype.isSVG = function(src) { + return (/(.+).svg$/i.test(src)) || SVGContainer.prototype.isInline(src); +}; + ImageLoader.prototype.imageExists = function(images, src) { return images.some(function(image) { return image.src === src; @@ -97,9 +106,21 @@ function isImage(container) { return container.node.nodeName === "IMG"; } +function isSVGNode(container) { + return container.node.nodeName === "svg"; +} + function urlImage(container) { return { args: [container.node.src], method: "url" }; } + +function svgImage(container) { + return { + args: [container.node], + method: "svg" + }; +} + diff --git a/src/nodecontainer.js b/src/nodecontainer.js index 44181a2..3804b9e 100644 --- a/src/nodecontainer.js +++ b/src/nodecontainer.js @@ -334,14 +334,14 @@ function getBounds(node) { if (node.getBoundingClientRect) { var clientRect = node.getBoundingClientRect(); var isBody = node.nodeName === "BODY"; - var width = isBody ? node.scrollWidth : node.offsetWidth; + var width = isBody ? node.scrollWidth : (node.offsetWidth == null ? clientRect.width : node.offsetWidth); return { top: clientRect.top, bottom: clientRect.bottom || (clientRect.top + clientRect.height), right: clientRect.left + width, left: clientRect.left, width: width, - height: isBody ? node.scrollHeight : node.offsetHeight + height: isBody ? node.scrollHeight : (node.offsetHeight == null ? clientRect.height : node.offsetHeight) }; } return {}; diff --git a/src/nodeparser.js b/src/nodeparser.js index bf3a019..d2495d4 100644 --- a/src/nodeparser.js +++ b/src/nodeparser.js @@ -249,8 +249,15 @@ NodeParser.prototype.paintNode = function(container) { this.renderer.renderBackground(container, bounds, borderData.borders.map(getWidth)); }, this); this.renderer.renderBorders(borderData.borders); - switch(container.node.nodeName) { + case "svg": + var svgContainer = this.images.get(container.node); + if (svgContainer) { + this.renderer.renderImage(container, bounds, borderData, svgContainer); + } else { + log("Error loading ", container.node); + } + break; case "IMG": var imageContainer = this.images.get(container.node.src); if (imageContainer) { diff --git a/src/svgcontainer.js b/src/svgcontainer.js index 9ba86f0..1397420 100644 --- a/src/svgcontainer.js +++ b/src/svgcontainer.js @@ -2,22 +2,42 @@ function SVGContainer(src) { this.src = src; this.image = null; var self = this; - this.promise = XHR(src).then(function(svg) { - return new Promise(function(resolve, reject) { - if (!html2canvas.fabric) { - return reject(new Error("html2canvas.svg.js is not loaded, cannot render svg")); - } - html2canvas.fabric.loadSVGFromString(svg, function (objects, options) { - var canvas = new html2canvas.fabric.StaticCanvas('c'); - self.image = canvas.lowerCanvasEl; - canvas - .setWidth(options.width) - .setHeight(options.height) - .add(html2canvas.fabric.util.groupSVGElements(objects, options)) - .renderAll(); - resolve(canvas.lowerCanvasEl); - }); + this.promise = this.hasFabric().then(function() { + return (self.isInline(src) ? Promise.resolve(self.inlineFormatting(src)) : XHR(src)); + }).then(function(svg) { + return new Promise(function(resolve) { + html2canvas.fabric.loadSVGFromString(svg, self.createCanvas.call(self, resolve)); }); }); } + +SVGContainer.prototype.hasFabric = function() { + return !html2canvas.fabric ? Promise.reject(new Error("html2canvas.svg.js is not loaded, cannot render svg")) : Promise.resolve(); +}; + +SVGContainer.prototype.inlineFormatting = function(src) { + return (/^data:image\/svg\+xml;base64,/.test(src)) ? window.atob(this.removeContentType(src)) : this.removeContentType(src); +}; + +SVGContainer.prototype.removeContentType = function(src) { + return src.replace(/^data:image\/svg\+xml(;base64)?,/,''); +}; + +SVGContainer.prototype.isInline = function(src) { + return (/^data:image\/svg\+xml/i.test(src)); +}; + +SVGContainer.prototype.createCanvas = function(resolve) { + var self = this; + return function (objects, options) { + var canvas = new html2canvas.fabric.StaticCanvas('c'); + self.image = canvas.lowerCanvasEl; + canvas + .setWidth(options.width) + .setHeight(options.height) + .add(html2canvas.fabric.util.groupSVGElements(objects, options)) + .renderAll(); + resolve(canvas.lowerCanvasEl); + }; +}; diff --git a/src/svgnodecontainer.js b/src/svgnodecontainer.js new file mode 100644 index 0000000..1896115 --- /dev/null +++ b/src/svgnodecontainer.js @@ -0,0 +1,13 @@ +function SVGNodeContainer(node) { + this.src = node; + this.image = null; + var self = this; + + this.promise = this.hasFabric().then(function() { + return new Promise(function(resolve) { + html2canvas.fabric.parseSVGDocument(node, self.createCanvas.call(self, resolve)); + }); + }); +} + +SVGNodeContainer.prototype = Object.create(SVGContainer.prototype); diff --git a/tests/cases/images/svg/base64.html b/tests/cases/images/svg/base64.html new file mode 100644 index 0000000..e52b478 --- /dev/null +++ b/tests/cases/images/svg/base64.html @@ -0,0 +1,13 @@ + + + + Base64 svg + + + + +
+ Inline svg image:
+
+ + diff --git a/tests/cases/images/svg/inline.html b/tests/cases/images/svg/inline.html new file mode 100644 index 0000000..8fb0f8d --- /dev/null +++ b/tests/cases/images/svg/inline.html @@ -0,0 +1,14 @@ + + + + Inline svg + + + + +
+ Inline svg image:
+ +
+ + diff --git a/tests/cases/images/svg/node.html b/tests/cases/images/svg/node.html new file mode 100644 index 0000000..5faa7a5 --- /dev/null +++ b/tests/cases/images/svg/node.html @@ -0,0 +1,20 @@ + + + + SVG node + + + +
+ SVG node image:
+ + + + + + +
+ + diff --git a/tests/test.js b/tests/test.js index 6e4b539..b80ce2a 100644 --- a/tests/test.js +++ b/tests/test.js @@ -12,7 +12,7 @@ var h2cSelector, h2cOptions; } var sources = ['log', 'nodecontainer', 'stackingcontext', 'textcontainer', 'support', 'imagecontainer', 'dummyimagecontainer', 'proxyimagecontainer', 'gradientcontainer', - 'lineargradientcontainer', 'webkitgradientcontainer', 'svgcontainer', 'imageloader', 'nodeparser', 'font', 'fontmetrics', 'core', 'renderer', 'promise', 'xhr', 'renderers/canvas']; + 'lineargradientcontainer', 'webkitgradientcontainer', 'svgcontainer', 'svgnodecontainer', 'imageloader', 'nodeparser', 'font', 'fontmetrics', 'core', 'renderer', 'promise', 'xhr', 'renderers/canvas']; ['/tests/assets/jquery-1.6.2'].concat(window.location.search === "?selenium" ? ['/dist/html2canvas'] : sources.map(function(src) { return '/src/' + src; })).forEach(appendScript);