diff --git a/.gitignore b/.gitignore index 0da05c1..b439c63 100644 --- a/.gitignore +++ b/.gitignore @@ -5,6 +5,7 @@ /tests/cache/ /tests/flashcanvas.html /lib/ +/build/ image.jpg /.project /.settings/ diff --git a/build/html2canvas.js b/build/html2canvas.js deleted file mode 100644 index d96769b..0000000 --- a/build/html2canvas.js +++ /dev/null @@ -1,3007 +0,0 @@ -/** - @license html2canvas v0.33 - Copyright (c) 2011 Niklas von Hertzen. All rights reserved. - http://www.twitter.com/niklasvh - - Released under MIT License - */ -(function(window, document, undefined){ -/* - html2canvas v0.33 - Copyright (c) 2011 Niklas von Hertzen. All rights reserved. - http://www.twitter.com/niklasvh - - Released under MIT License - */ -"use strict"; - -var _html2canvas = {}, -html2canvas; - - -function h2clog(a) { - if (_html2canvas.logging && window.console && window.console.log) { - window.console.log(a); - } -} - -_html2canvas.Util = {}; - -_html2canvas.Util.backgroundImage = function (src) { - - if (/data:image\/.*;base64,/i.test( src ) || /^(-webkit|-moz|linear-gradient|-o-)/.test( src )) { - return src; - } - - if (src.toLowerCase().substr( 0, 5 ) === 'url("') { - src = src.substr( 5 ); - src = src.substr( 0, src.length - 2 ); - } else { - src = src.substr( 4 ); - src = src.substr( 0, src.length - 1 ); - } - - return src; -}; - -_html2canvas.Util.Bounds = function getBounds (el) { - var clientRect, - bounds = {}; - - if (el.getBoundingClientRect){ - clientRect = el.getBoundingClientRect(); - - - // TODO add scroll position to bounds, so no scrolling of window necessary - bounds.top = clientRect.top; - bounds.bottom = clientRect.bottom || (clientRect.top + clientRect.height); - bounds.left = clientRect.left; - - // older IE doesn't have width/height, but top/bottom instead - bounds.width = clientRect.width || (clientRect.right - clientRect.left); - bounds.height = clientRect.height || (clientRect.bottom - clientRect.top); - - return bounds; - - } -}; - -_html2canvas.Util.getCSS = function (el, attribute) { - // return $(el).css(attribute); - - var val; - - function toPX( attribute, val ) { - var rsLeft = el.runtimeStyle && el.runtimeStyle[ attribute ], - left, - style = el.style; - - // Check if we are not dealing with pixels, (Opera has issues with this) - // Ported from jQuery css.js - // From the awesome hack by Dean Edwards - // http://erik.eae.net/archives/2007/07/27/18.54.15/#comment-102291 - - // If we're not dealing with a regular pixel number - // but a number that has a weird ending, we need to convert it to pixels - - if ( !/^-?[0-9]+\.?[0-9]*(?:px)?$/i.test( val ) && /^-?\d/.test( val ) ) { - - // Remember the original values - left = style.left; - - // Put in the new values to get a computed value out - if ( rsLeft ) { - el.runtimeStyle.left = el.currentStyle.left; - } - style.left = attribute === "fontSize" ? "1em" : (val || 0); - val = style.pixelLeft + "px"; - - // Revert the changed values - style.left = left; - if ( rsLeft ) { - el.runtimeStyle.left = rsLeft; - } - - } - - if (!/^(thin|medium|thick)$/i.test( val )) { - return Math.round(parseFloat( val )) + "px"; - } - - return val; - - } - - - if ( window.getComputedStyle ) { - val = document.defaultView.getComputedStyle(el, null)[ attribute ]; - - if ( attribute === "backgroundPosition" ) { - - val = (val.split(",")[0] || "0 0").split(" "); - - val[ 0 ] = ( val[0].indexOf( "%" ) === -1 ) ? toPX( attribute + "X", val[ 0 ] ) : val[ 0 ]; - val[ 1 ] = ( val[1] === undefined ) ? val[0] : val[1]; // IE 9 doesn't return double digit always - val[ 1 ] = ( val[1].indexOf( "%" ) === -1 ) ? toPX( attribute + "Y", val[ 1 ] ) : val[ 1 ]; - } - - } else if ( el.currentStyle ) { - // IE 9> - if (attribute === "backgroundPosition") { - // Older IE uses -x and -y - val = [ toPX( attribute + "X", el.currentStyle[ attribute + "X" ] ), toPX( attribute + "Y", el.currentStyle[ attribute + "Y" ] ) ]; - } else { - - val = toPX( attribute, el.currentStyle[ attribute ] ); - - if (/^(border)/i.test( attribute ) && /^(medium|thin|thick)$/i.test( val )) { - switch (val) { - case "thin": - val = "1px"; - break; - case "medium": - val = "0px"; // this is wrong, it should be 3px but IE uses medium for no border as well.. TODO find a work around - break; - case "thick": - val = "5px"; - break; - } - } - } - - - - } - - - - - return val; - - - -//return $(el).css(attribute); - - -}; - - -_html2canvas.Util.BackgroundPosition = function ( el, bounds, image ) { - // TODO add support for multi image backgrounds - - var bgposition = _html2canvas.Util.getCSS( el, "backgroundPosition" ) , - topPos, - left, - percentage, - val; - - if (bgposition.length === 1){ - val = bgposition; - - bgposition = []; - - bgposition[0] = val; - bgposition[1] = val; - } - - - - if (bgposition[0].toString().indexOf("%") !== -1){ - percentage = (parseFloat(bgposition[0])/100); - left = ((bounds.width * percentage)-(image.width*percentage)); - - }else{ - left = parseInt(bgposition[0],10); - } - - if (bgposition[1].toString().indexOf("%") !== -1){ - - percentage = (parseFloat(bgposition[1])/100); - topPos = ((bounds.height * percentage)-(image.height*percentage)); - }else{ - topPos = parseInt(bgposition[1],10); - } - - - - - return { - top: topPos, - left: left - }; - -}; - -_html2canvas.Util.Extend = function (options, defaults) { - for (var key in options) { - if (options.hasOwnProperty(key)) { - defaults[key] = options[key]; - } - } - return defaults; -}; - -_html2canvas.Util.Children = function(el) { - // $(el).contents() !== el.childNodes, Opera / IE have issues with that - var children; - try { - children = $(el).contents(); - //children = (el.nodeName && el.nodeName.toUpperCase() === "IFRAME") ? el.contentDocument || el.contentWindow.document : el.childNodes ; - - } catch (ex) { - h2clog("html2canvas.Util.Children failed with exception: " + ex.message); - children = []; - } - return children; -}; -/* - html2canvas v0.33 - Copyright (c) 2011 Niklas von Hertzen. All rights reserved. - http://www.twitter.com/niklasvh - - Contributor(s): - Niklas von Hertzen - André Fiedler - - Released under MIT License - */ - -(function(){ - -_html2canvas.Generate = {}; - -var reGradients = [ - /^(-webkit-linear-gradient)\(([a-z\s]+)([\w\d\.\s,%\(\)]+)\)$/, - /^(-o-linear-gradient)\(([a-z\s]+)([\w\d\.\s,%\(\)]+)\)$/, - /^(-webkit-gradient)\((linear|radial),\s((?:\d{1,3}%?)\s(?:\d{1,3}%?),\s(?:\d{1,3}%?)\s(?:\d{1,3}%?))([\w\d\.\s,%\(\)-]+)\)$/, - /^(-moz-linear-gradient)\(((?:\d{1,3}%?)\s(?:\d{1,3}%?))([\w\d\.\s,%\(\)]+)\)$/, - /^(-webkit-radial-gradient)\(((?:\d{1,3}%?)\s(?:\d{1,3}%?)),\s(\w+)\s([a-z-]+)([\w\d\.\s,%\(\)]+)\)$/, - /^(-moz-radial-gradient)\(((?:\d{1,3}%?)\s(?:\d{1,3}%?)),\s(\w+)\s?([a-z-]*)([\w\d\.\s,%\(\)]+)\)$/, - /^(-o-radial-gradient)\(((?:\d{1,3}%?)\s(?:\d{1,3}%?)),\s(\w+)\s([a-z-]+)([\w\d\.\s,%\(\)]+)\)$/ -]; - -/* - * TODO: Add IE10 vendor prefix (-ms) support - * TODO: Add W3C gradient (linear-gradient) support - * TODO: Add old Webkit -webkit-gradient(radial, ...) support - * TODO: Maybe some RegExp optimizations are possible ;o) - */ -_html2canvas.Generate.parseGradient = function(css, bounds) { - var gradient, i, len = reGradients.length, m1, stop, m2, m2Len, step, m3; - - for(i = 0; i < len; i+=1){ - m1 = css.match(reGradients[i]); - if(m1) break; - } - - if(m1) { - switch(m1[1]) { - case '-webkit-linear-gradient': - case '-o-linear-gradient': - - gradient = { - type: 'linear', - x0: null, - y0: null, - x1: null, - y1: null, - colorStops: [] - }; - - // get coordinates - m2 = m1[2].match(/\w+/g); - if(m2){ - m2Len = m2.length; - for(i = 0; i < m2Len; i+=1){ - switch(m2[i]) { - case 'top': - gradient.y0 = 0; - gradient.y1 = bounds.height; - break; - - case 'right': - gradient.x0 = bounds.width; - gradient.x1 = 0; - break; - - case 'bottom': - gradient.y0 = bounds.height; - gradient.y1 = 0; - break; - - case 'left': - gradient.x0 = 0; - gradient.x1 = bounds.width; - break; - } - } - } - if(gradient.x0 === null && gradient.x1 === null){ // center - gradient.x0 = gradient.x1 = bounds.width / 2; - } - if(gradient.y0 === null && gradient.y1 === null){ // center - gradient.y0 = gradient.y1 = bounds.height / 2; - } - - // get colors and stops - m2 = m1[3].match(/((?:rgb|rgba)\(\d{1,3},\s\d{1,3},\s\d{1,3}(?:,\s[0-9\.]+)?\)(?:\s\d{1,3}(?:%|px))?)+/g); - if(m2){ - m2Len = m2.length; - step = 1 / Math.max(m2Len - 1, 1); - for(i = 0; i < m2Len; i+=1){ - m3 = m2[i].match(/((?:rgb|rgba)\(\d{1,3},\s\d{1,3},\s\d{1,3}(?:,\s[0-9\.]+)?\))\s*(\d{1,3})?(%|px)?/); - if(m3[2]){ - stop = parseFloat(m3[2]); - if(m3[3] === '%'){ - stop /= 100; - } else { // px - stupid opera - stop /= bounds.width; - } - } else { - stop = i * step; - } - gradient.colorStops.push({ - color: m3[1], - stop: stop - }); - } - } - break; - - case '-webkit-gradient': - - gradient = { - type: m1[2] === 'radial' ? 'circle' : m1[2], // TODO: Add radial gradient support for older mozilla definitions - x0: 0, - y0: 0, - x1: 0, - y1: 0, - colorStops: [] - }; - - // get coordinates - m2 = m1[3].match(/(\d{1,3})%?\s(\d{1,3})%?,\s(\d{1,3})%?\s(\d{1,3})%?/); - if(m2){ - gradient.x0 = (m2[1] * bounds.width) / 100; - gradient.y0 = (m2[2] * bounds.height) / 100; - gradient.x1 = (m2[3] * bounds.width) / 100; - gradient.y1 = (m2[4] * bounds.height) / 100; - } - - // get colors and stops - m2 = m1[4].match(/((?:from|to|color-stop)\((?:[0-9\.]+,\s)?(?:rgb|rgba)\(\d{1,3},\s\d{1,3},\s\d{1,3}(?:,\s[0-9\.]+)?\)\))+/g); - if(m2){ - m2Len = m2.length; - for(i = 0; i < m2Len; i+=1){ - m3 = m2[i].match(/(from|to|color-stop)\(([0-9\.]+)?(?:,\s)?((?:rgb|rgba)\(\d{1,3},\s\d{1,3},\s\d{1,3}(?:,\s[0-9\.]+)?\))\)/); - stop = parseFloat(m3[2]); - if(m3[1] === 'from') stop = 0.0; - if(m3[1] === 'to') stop = 1.0; - gradient.colorStops.push({ - color: m3[3], - stop: stop - }); - } - } - break; - - case '-moz-linear-gradient': - - gradient = { - type: 'linear', - x0: 0, - y0: 0, - x1: 0, - y1: 0, - colorStops: [] - }; - - // get coordinates - m2 = m1[2].match(/(\d{1,3})%?\s(\d{1,3})%?/); - - // m2[1] == 0% -> left - // m2[1] == 50% -> center - // m2[1] == 100% -> right - - // m2[2] == 0% -> top - // m2[2] == 50% -> center - // m2[2] == 100% -> bottom - - if(m2){ - gradient.x0 = (m2[1] * bounds.width) / 100; - gradient.y0 = (m2[2] * bounds.height) / 100; - gradient.x1 = bounds.width - gradient.x0; - gradient.y1 = bounds.height - gradient.y0; - } - - // get colors and stops - m2 = m1[3].match(/((?:rgb|rgba)\(\d{1,3},\s\d{1,3},\s\d{1,3}(?:,\s[0-9\.]+)?\)(?:\s\d{1,3}%)?)+/g); - if(m2){ - m2Len = m2.length; - step = 1 / Math.max(m2Len - 1, 1); - for(i = 0; i < m2Len; i+=1){ - m3 = m2[i].match(/((?:rgb|rgba)\(\d{1,3},\s\d{1,3},\s\d{1,3}(?:,\s[0-9\.]+)?\))\s*(\d{1,3})?(%)?/); - if(m3[2]){ - stop = parseFloat(m3[2]); - if(m3[3]){ // percentage - stop /= 100; - } - } else { - stop = i * step; - } - gradient.colorStops.push({ - color: m3[1], - stop: stop - }); - } - } - break; - - case '-webkit-radial-gradient': - case '-moz-radial-gradient': - case '-o-radial-gradient': - - gradient = { - type: 'circle', - x0: 0, - y0: 0, - x1: bounds.width, - y1: bounds.height, - cx: 0, - cy: 0, - rx: 0, - ry: 0, - colorStops: [] - }; - - // center - m2 = m1[2].match(/(\d{1,3})%?\s(\d{1,3})%?/); - if(m2){ - gradient.cx = (m2[1] * bounds.width) / 100; - gradient.cy = (m2[2] * bounds.height) / 100; - } - - // size - m2 = m1[3].match(/\w+/); - m3 = m1[4].match(/[a-z-]*/); - if(m2 && m3){ - switch(m3[0]){ - case 'farthest-corner': - case 'cover': // is equivalent to farthest-corner - case '': // mozilla removes "cover" from definition :( - var tl = Math.sqrt(Math.pow(gradient.cx, 2) + Math.pow(gradient.cy, 2)); - var tr = Math.sqrt(Math.pow(gradient.cx, 2) + Math.pow(gradient.y1 - gradient.cy, 2)); - var br = Math.sqrt(Math.pow(gradient.x1 - gradient.cx, 2) + Math.pow(gradient.y1 - gradient.cy, 2)); - var bl = Math.sqrt(Math.pow(gradient.x1 - gradient.cx, 2) + Math.pow(gradient.cy, 2)); - gradient.rx = gradient.ry = Math.max(tl, tr, br, bl); - break; - case 'closest-corner': - var tl = Math.sqrt(Math.pow(gradient.cx, 2) + Math.pow(gradient.cy, 2)); - var tr = Math.sqrt(Math.pow(gradient.cx, 2) + Math.pow(gradient.y1 - gradient.cy, 2)); - var br = Math.sqrt(Math.pow(gradient.x1 - gradient.cx, 2) + Math.pow(gradient.y1 - gradient.cy, 2)); - var bl = Math.sqrt(Math.pow(gradient.x1 - gradient.cx, 2) + Math.pow(gradient.cy, 2)); - gradient.rx = gradient.ry = Math.min(tl, tr, br, bl); - break; - case 'farthest-side': - if(m2[0] === 'circle'){ - gradient.rx = gradient.ry = Math.max( - gradient.cx, - gradient.cy, - gradient.x1 - gradient.cx, - gradient.y1 - gradient.cy - ); - } else { // ellipse - - gradient.type = m2[0]; - - gradient.rx = Math.max( - gradient.cx, - gradient.x1 - gradient.cx - ); - gradient.ry = Math.max( - gradient.cy, - gradient.y1 - gradient.cy - ); - } - break; - case 'closest-side': - case 'contain': // is equivalent to closest-side - if(m2[0] === 'circle'){ - gradient.rx = gradient.ry = Math.min( - gradient.cx, - gradient.cy, - gradient.x1 - gradient.cx, - gradient.y1 - gradient.cy - ); - } else { // ellipse - - gradient.type = m2[0]; - - gradient.rx = Math.min( - gradient.cx, - gradient.x1 - gradient.cx - ); - gradient.ry = Math.min( - gradient.cy, - gradient.y1 - gradient.cy - ); - } - break; - - // TODO: add support for "30px 40px" sizes (webkit only) - } - } - - // color stops - m2 = m1[5].match(/((?:rgb|rgba)\(\d{1,3},\s\d{1,3},\s\d{1,3}(?:,\s[0-9\.]+)?\)(?:\s\d{1,3}(?:%|px))?)+/g); - if(m2){ - m2Len = m2.length; - step = 1 / Math.max(m2Len - 1, 1); - for(i = 0; i < m2Len; i+=1){ - m3 = m2[i].match(/((?:rgb|rgba)\(\d{1,3},\s\d{1,3},\s\d{1,3}(?:,\s[0-9\.]+)?\))\s*(\d{1,3})?(%|px)?/); - if(m3[2]){ - stop = parseFloat(m3[2]); - if(m3[3] === '%'){ - stop /= 100; - } else { // px - stupid opera - stop /= bounds.width; - } - } else { - stop = i * step; - } - gradient.colorStops.push({ - color: m3[1], - stop: stop - }); - } - } - break; - } - } - - return gradient; -}; - -_html2canvas.Generate.Gradient = function(src, bounds) { - var canvas = document.createElement('canvas'), - ctx = canvas.getContext('2d'), - gradient, grad, i, len, img; - - canvas.width = bounds.width; - canvas.height = bounds.height; - - // TODO: add support for multi defined background gradients (like radial gradient example in background.html) - gradient = _html2canvas.Generate.parseGradient(src, bounds); - - img = new Image(); - - if(gradient){ - if(gradient.type === 'linear'){ - grad = ctx.createLinearGradient(gradient.x0, gradient.y0, gradient.x1, gradient.y1); - - for (i = 0, len = gradient.colorStops.length; i < len; i+=1) { - try { - grad.addColorStop(gradient.colorStops[i].stop, gradient.colorStops[i].color); - } - catch(e) { - h2clog(['failed to add color stop: ', e, '; tried to add: ', gradient.colorStops[i], '; stop: ', i, '; in: ', src]); - } - } - - ctx.fillStyle = grad; - ctx.fillRect(0, 0, bounds.width, bounds.height); - - img.src = canvas.toDataURL(); - } else if(gradient.type === 'circle'){ - - grad = ctx.createRadialGradient(gradient.cx, gradient.cy, 0, gradient.cx, gradient.cy, gradient.rx); - - for (i = 0, len = gradient.colorStops.length; i < len; i+=1) { - try { - grad.addColorStop(gradient.colorStops[i].stop, gradient.colorStops[i].color); - } - catch(e) { - h2clog(['failed to add color stop: ', e, '; tried to add: ', gradient.colorStops[i], '; stop: ', i, '; in: ', src]); - } - } - - ctx.fillStyle = grad; - ctx.fillRect(0, 0, bounds.width, bounds.height); - - img.src = canvas.toDataURL(); - } else if(gradient.type === 'ellipse'){ - - // draw circle - var canvasRadial = document.createElement('canvas'), - ctxRadial = canvasRadial.getContext('2d'), - ri = Math.max(gradient.rx, gradient.ry), - di = ri * 2, imgRadial; - - canvasRadial.width = canvasRadial.height = di; - - grad = ctxRadial.createRadialGradient(gradient.rx, gradient.ry, 0, gradient.rx, gradient.ry, ri); - - for (i = 0, len = gradient.colorStops.length; i < len; i+=1) { - try { - grad.addColorStop(gradient.colorStops[i].stop, gradient.colorStops[i].color); - } - catch(e) { - h2clog(['failed to add color stop: ', e, '; tried to add: ', gradient.colorStops[i], '; stop: ', i, '; in: ', src]); - } - } - - ctxRadial.fillStyle = grad; - ctxRadial.fillRect(0, 0, di, di); - - ctx.fillStyle = gradient.colorStops[i - 1].color; - ctx.fillRect(0, 0, canvas.width, canvas.height); - - imgRadial = new Image(); - imgRadial.onload = function() { // wait until the image is filled - - // transform circle to ellipse - ctx.drawImage(imgRadial, gradient.cx - gradient.rx, gradient.cy - gradient.ry, 2 * gradient.rx, 2 * gradient.ry); - - img.src = canvas.toDataURL(); - - } - imgRadial.src = canvasRadial.toDataURL(); - } - } - - return img; -}; - -_html2canvas.Generate.ListAlpha = function(number) { - var tmp = "", - modulus; - - do { - modulus = number % 26; - tmp = String.fromCharCode((modulus) + 64) + tmp; - number = number / 26; - }while((number*26) > 26); - - return tmp; -}; - -_html2canvas.Generate.ListRoman = function(number) { - var romanArray = ["M", "CM", "D", "CD", "C", "XC", "L", "XL", "X", "IX", "V", "IV", "I"], - decimal = [1000, 900, 500, 400, 100, 90, 50, 40, 10, 9, 5, 4, 1], - roman = "", - v, - len = romanArray.length; - - if (number <= 0 || number >= 4000) { - return number; - } - - for (v=0; v < len; v+=1) { - while (number >= decimal[v]) { - number -= decimal[v]; - roman += romanArray[v]; - } - } - - return roman; - -}; - -})(); -/* - html2canvas v0.33 - Copyright (c) 2011 Niklas von Hertzen. All rights reserved. - http://www.twitter.com/niklasvh - - Released under MIT License -*/ - -/* - * New function for traversing elements - */ - -_html2canvas.Parse = function ( images, options ) { - window.scroll(0,0); - - var support = { - rangeBounds: false, - svgRendering: options.svgRendering && (function( ){ - var img = new Image(), - canvas = document.createElement("canvas"), - ctx = (canvas.getContext === undefined) ? false : canvas.getContext("2d"); - if (ctx === false) { - // browser doesn't support canvas, good luck supporting SVG on canvas - return false; - } - canvas.width = canvas.height = 10; - img.src = [ - "data:image/svg+xml,", - "", - "", - "
", - "sup", - "
", - "
", - "
" - ].join(""); - try { - ctx.drawImage(img, 0, 0); - canvas.toDataURL(); - } catch(e) { - return false; - } - h2clog('html2canvas: Parse: SVG powered rendering available'); - return true; - - })() - }, - element = (( options.elements === undefined ) ? document.body : options.elements[0]), // select body by default - needReorder = false, - numDraws = 0, - fontData = {}, - doc = element.ownerDocument, - ignoreElementsRegExp = new RegExp("(" + options.ignoreElements + ")"), - body = doc.body, - r, - testElement, - rangeBounds, - rangeHeight, - stack, - ctx, - docDim, - i, - children, - childrenLen; - - - function docSize(){ - - return { - width: Math.max( - Math.max(doc.body.scrollWidth, doc.documentElement.scrollWidth), - Math.max(doc.body.offsetWidth, doc.documentElement.offsetWidth), - Math.max(doc.body.clientWidth, doc.documentElement.clientWidth) - ), - height: Math.max( - Math.max(doc.body.scrollHeight, doc.documentElement.scrollHeight), - Math.max(doc.body.offsetHeight, doc.documentElement.offsetHeight), - Math.max(doc.body.clientHeight, doc.documentElement.clientHeight) - ) - }; - - } - - images = images || {}; - - // Test whether we can use ranges to measure bounding boxes - // Opera doesn't provide valid bounds.height/bottom even though it supports the method. - - - if (doc.createRange) { - r = doc.createRange(); - //this.support.rangeBounds = new Boolean(r.getBoundingClientRect); - if (r.getBoundingClientRect){ - testElement = doc.createElement('boundtest'); - testElement.style.height = "123px"; - testElement.style.display = "block"; - body.appendChild(testElement); - - r.selectNode(testElement); - rangeBounds = r.getBoundingClientRect(); - rangeHeight = rangeBounds.height; - - if (rangeHeight === 123) { - support.rangeBounds = true; - } - body.removeChild(testElement); - - - } - - } - - - /* - var rootStack = new this.storageContext($(document).width(),$(document).height()); - rootStack.opacity = this.getCSS(this.element,"opacity"); - var stack = this.newElement(this.element,rootStack); - - - this.parseElement(this.element,stack); - */ - - - - - var getCSS = _html2canvas.Util.getCSS; - function getCSSInt(element, attribute) { - var val = parseInt(getCSS(element, attribute), 10); - return (isNaN(val)) ? 0 : val; // borders in old IE are throwing 'medium' for demo.html - } - - // Drawing a rectangle - function renderRect (ctx, x, y, w, h, bgcolor) { - if (bgcolor !=="transparent"){ - ctx.setVariable("fillStyle", bgcolor); - ctx.fillRect (x, y, w, h); - numDraws+=1; - } - } - - - function textTransform (text, transform) { - switch(transform){ - case "lowercase": - return text.toLowerCase(); - - case "capitalize": - return text.replace( /(^|\s|:|-|\(|\))([a-z])/g , function (m, p1, p2) { - if (m.length > 0) { - return p1 + p2.toUpperCase(); - } - } ); - - case "uppercase": - return text.toUpperCase(); - - default: - return text; - - } - - } - - function trimText (text) { - return text.replace(/^\s*/g, "").replace(/\s*$/g, ""); - } - - function fontMetrics (font, fontSize) { - - if (fontData[font + "-" + fontSize] !== undefined) { - return fontData[font + "-" + fontSize]; - } - - - var container = doc.createElement('div'), - img = doc.createElement('img'), - span = doc.createElement('span'), - baseline, - middle, - metricsObj; - - - container.style.visibility = "hidden"; - container.style.fontFamily = font; - container.style.fontSize = fontSize; - container.style.margin = 0; - container.style.padding = 0; - - body.appendChild(container); - - - - // http://probablyprogramming.com/2009/03/15/the-tiniest-gif-ever (handtinywhite.gif) - img.src = "data:image/gif;base64,R0lGODlhAQABAIABAP///wAAACwAAAAAAQABAAACAkQBADs="; - img.width = 1; - img.height = 1; - - img.style.margin = 0; - img.style.padding = 0; - img.style.verticalAlign = "baseline"; - - span.style.fontFamily = font; - span.style.fontSize = fontSize; - span.style.margin = 0; - span.style.padding = 0; - - - - - span.appendChild(doc.createTextNode('Hidden Text')); - container.appendChild(span); - container.appendChild(img); - baseline = (img.offsetTop - span.offsetTop) + 1; - - container.removeChild(span); - container.appendChild(doc.createTextNode('Hidden Text')); - - container.style.lineHeight = "normal"; - img.style.verticalAlign = "super"; - - middle = (img.offsetTop-container.offsetTop) + 1; - metricsObj = { - baseline: baseline, - lineWidth: 1, - middle: middle - }; - - - fontData[font + "-" + fontSize] = metricsObj; - - body.removeChild(container); - - return metricsObj; - - } - - - function drawText(currentText, x, y, ctx){ - if (trimText(currentText).length>0) { - ctx.fillText(currentText,x,y); - numDraws+=1; - } - } - - - function renderText(el, textNode, stack) { - var ctx = stack.ctx, - family = getCSS(el, "fontFamily"), - size = getCSS(el, "fontSize"), - color = getCSS(el, "color"), - text_decoration = getCSS(el, "textDecoration"), - text_align = getCSS(el, "textAlign"), - letter_spacing = getCSS(el, "letterSpacing"), - bounds, - text, - metrics, - renderList, - listLen, - bold = getCSS(el, "fontWeight"), - font_style = getCSS(el, "fontStyle"), - font_variant = getCSS(el, "fontVariant"), - align = false, - newTextNode, - textValue, - textOffset = 0, - oldTextNode, - c, - range, - parent, - wrapElement, - backupText; - - // apply text-transform:ation to the text - - - - textNode.nodeValue = textTransform(textNode.nodeValue, getCSS(el, "textTransform")); - text = trimText(textNode.nodeValue); - - if (text.length>0){ - - if (text_decoration !== "none"){ - metrics = fontMetrics(family, size); - } - - text_align = text_align.replace(["-webkit-auto"],["auto"]); - - if (options.letterRendering === false && /^(left|right|justify|auto)$/.test(text_align) && /^(normal|none)$/.test(letter_spacing)){ - // this.setContextVariable(ctx,"textAlign",text_align); - renderList = textNode.nodeValue.split(/(\b| )/); - - }else{ - // this.setContextVariable(ctx,"textAlign","left"); - renderList = textNode.nodeValue.split(""); - } - - switch(parseInt(bold, 10)){ - case 401: - bold = "bold"; - break; - case 400: - bold = "normal"; - break; - } - - ctx.setVariable("fillStyle", color); - - /* - need to be defined in the order as defined in http://www.w3.org/TR/CSS21/fonts.html#font-shorthand - to properly work in Firefox - */ - ctx.setVariable("font", font_style+ " " + font_variant + " " + bold + " " + size + " " + family); - - if (align){ - ctx.setVariable("textAlign", "right"); - }else{ - ctx.setVariable("textAlign", "left"); - } - - - /* - if (stack.clip){ - ctx.rect (stack.clip.left, stack.clip.top, stack.clip.width, stack.clip.height); - ctx.clip(); - } - */ - - - oldTextNode = textNode; - - - for ( c=0, listLen = renderList.length; c < listLen; c+=1 ) { - textValue = null; - - - - if (support.rangeBounds){ - // getBoundingClientRect is supported for ranges - if (text_decoration !== "none" || trimText(renderList[c]).length !== 0) { - textValue = renderList[c]; - if (doc.createRange){ - range = doc.createRange(); - - range.setStart(textNode, textOffset); - range.setEnd(textNode, textOffset + textValue.length); - }else{ - // TODO add IE support - range = body.createTextRange(); - } - - if (range.getBoundingClientRect()) { - bounds = range.getBoundingClientRect(); - }else{ - bounds = {}; - } - - } - }else{ - // it isn't supported, so let's wrap it inside an element instead and get the bounds there - - // IE 9 bug - if (typeof oldTextNode.nodeValue !== "string" ){ - continue; - } - - newTextNode = oldTextNode.splitText(renderList[c].length); - - parent = oldTextNode.parentNode; - wrapElement = doc.createElement('wrapper'); - backupText = oldTextNode.cloneNode(true); - - wrapElement.appendChild(oldTextNode.cloneNode(true)); - parent.replaceChild(wrapElement, oldTextNode); - - bounds = _html2canvas.Util.Bounds(wrapElement); - - textValue = oldTextNode.nodeValue; - - oldTextNode = newTextNode; - parent.replaceChild(backupText, wrapElement); - - - } - - if (textValue !== null){ - drawText(textValue, bounds.left, bounds.bottom, ctx); - } - - switch(text_decoration) { - case "underline": - // Draws a line at the baseline of the font - // TODO As some browsers display the line as more than 1px if the font-size is big, need to take that into account both in position and size - renderRect(ctx, bounds.left, Math.round(bounds.top + metrics.baseline + metrics.lineWidth), bounds.width, 1, color); - break; - case "overline": - renderRect(ctx, bounds.left, bounds.top, bounds.width, 1, color); - break; - case "line-through": - // TODO try and find exact position for line-through - renderRect(ctx, bounds.left, Math.ceil(bounds.top + metrics.middle + metrics.lineWidth), bounds.width, 1, color); - break; - - } - - - - - - textOffset += renderList[c].length; - - } - - - - } - - } - - function listPosition (element, val) { - var boundElement = doc.createElement( "boundelement" ), - type, - bounds; - - boundElement.style.display = "inline"; - //boundElement.style.width = "1px"; - //boundElement.style.height = "1px"; - - type = element.style.listStyleType; - element.style.listStyleType = "none"; - - boundElement.appendChild( doc.createTextNode( val ) ); - - - element.insertBefore(boundElement, element.firstChild); - - - bounds = _html2canvas.Util.Bounds( boundElement ); - element.removeChild( boundElement ); - element.style.listStyleType = type; - return bounds; - - } - - - function renderListItem(element, stack, elBounds) { - - - var position = getCSS(element, "listStylePosition"), - x, - y, - type = getCSS(element, "listStyleType"), - currentIndex, - text, - listBounds, - bold = getCSS(element, "fontWeight"); - - if (/^(decimal|decimal-leading-zero|upper-alpha|upper-latin|upper-roman|lower-alpha|lower-greek|lower-latin|lower-roman)$/i.test(type)) { - - // TODO remove jQuery dependency - currentIndex = $(element).index()+1; - - switch(type){ - case "decimal": - text = currentIndex; - break; - case "decimal-leading-zero": - if (currentIndex.toString().length === 1){ - text = currentIndex = "0" + currentIndex.toString(); - }else{ - text = currentIndex.toString(); - } - break; - case "upper-roman": - text = _html2canvas.Generate.ListRoman( currentIndex ); - break; - case "lower-roman": - text = _html2canvas.Generate.ListRoman( currentIndex ).toLowerCase(); - break; - case "lower-alpha": - text = _html2canvas.Generate.ListAlpha( currentIndex ).toLowerCase(); - break; - case "upper-alpha": - text = _html2canvas.Generate.ListAlpha( currentIndex ); - break; - } - - - text += ". "; - listBounds = listPosition(element, text); - - - - switch(bold){ - case 401: - bold = "bold"; - break; - case 400: - bold = "normal"; - break; - } - - - - - ctx.setVariable( "fillStyle", getCSS(element, "color") ); - ctx.setVariable( "font", getCSS(element, "fontVariant") + " " + bold + " " + getCSS(element, "fontStyle") + " " + getCSS(element, "fontSize") + " " + getCSS(element, "fontFamily") ); - - - if ( position === "inside" ) { - ctx.setVariable("textAlign", "left"); - // this.setFont(stack.ctx, element, false); - x = elBounds.left; - - }else{ - return; - /* - TODO really need to figure out some more accurate way to try and find the position. - as defined in http://www.w3.org/TR/CSS21/generate.html#propdef-list-style-position, it does not even have a specified "correct" position, so each browser - may display it whatever way it feels like. - "The position of the list-item marker adjacent to floats is undefined in CSS 2.1. CSS 2.1 does not specify the precise location of the marker box or its position in the painting order" - - ctx.setVariable("textAlign", "right"); - // this.setFont(stack.ctx, element, true); - x = elBounds.left - 10; - */ - } - - y = listBounds.bottom; - - drawText(text, x, y, ctx); - - - } - - - } - - function loadImage (src){ - var img = images[src]; - if (img && img.succeeded === true) { - return img.img; - } else { - return false; - } - } - - - - - - - function clipBounds(src, dst){ - - var x = Math.max(src.left, dst.left), - y = Math.max(src.top, dst.top), - x2 = Math.min((src.left + src.width), (dst.left + dst.width)), - y2 = Math.min((src.top + src.height), (dst.top + dst.height)); - - return { - left:x, - top:y, - width:x2-x, - height:y2-y - }; - - } - - function setZ(zIndex, parentZ){ - // TODO fix static elements overlapping relative/absolute elements under same stack, if they are defined after them - var newContext; - if (!parentZ){ - newContext = h2czContext(0); - return newContext; - } - - if (zIndex !== "auto"){ - needReorder = true; - newContext = h2czContext(zIndex); - parentZ.children.push(newContext); - return newContext; - - } - - return parentZ; - - } - - function renderBorders(el, ctx, bounds, clip){ - - /* - * TODO add support for different border-style's than solid - */ - - var x = bounds.left, - y = bounds.top, - w = bounds.width, - h = bounds.height, - borderSide, - borderData, - bx, - by, - bw, - bh, - borderBounds, - borders = (function(el){ - var borders = [], - sides = ["Top","Right","Bottom","Left"], - s; - - for (s = 0; s < 4; s+=1){ - borders.push({ - width: getCSSInt(el, 'border' + sides[s] + 'Width'), - color: getCSS(el, 'border' + sides[s] + 'Color') - }); - } - - return borders; - - }(el)); - - - for (borderSide = 0; borderSide < 4; borderSide+=1){ - borderData = borders[borderSide]; - - if (borderData.width>0){ - bx = x; - by = y; - bw = w; - bh = h - (borders[2].width); - - switch(borderSide){ - case 0: - // top border - bh = borders[0].width; - break; - case 1: - // right border - bx = x + w - (borders[1].width); - bw = borders[1].width; - break; - case 2: - // bottom border - by = (by + h) - (borders[2].width); - bh = borders[2].width; - break; - case 3: - // left border - bw = borders[3].width; - break; - } - - borderBounds = { - left:bx, - top:by, - width: bw, - height:bh - }; - - if (clip){ - borderBounds = clipBounds(borderBounds, clip); - } - - - if (borderBounds.width>0 && borderBounds.height>0){ - renderRect(ctx, bx, by, borderBounds.width, borderBounds.height, borderData.color); - } - - - } - } - - return borders; - - } - - - function renderFormValue (el, bounds, stack){ - - var valueWrap = doc.createElement('valuewrap'), - cssArr = ['lineHeight','textAlign','fontFamily','color','fontSize','paddingLeft','paddingTop','width','height','border','borderLeftWidth','borderTopWidth'], - i, - textValue, - textNode, - arrLen, - style; - - for (i = 0, arrLen = cssArr.length; i < arrLen; i+=1){ - style = cssArr[i]; - - try { - valueWrap.style[style] = getCSS(el, style); - } catch( e ) { - // Older IE has issues with "border" - h2clog("html2canvas: Parse: Exception caught in renderFormValue: " + e.message); - } - } - - - valueWrap.style.borderColor = "black"; - valueWrap.style.borderStyle = "solid"; - valueWrap.style.display = "block"; - valueWrap.style.position = "absolute"; - if (/^(submit|reset|button|text|password)$/.test(el.type) || el.nodeName === "SELECT"){ - valueWrap.style.lineHeight = getCSS(el, "height"); - } - - - valueWrap.style.top = bounds.top + "px"; - valueWrap.style.left = bounds.left + "px"; - - if (el.nodeName === "SELECT"){ - // TODO increase accuracy of text position - textValue = el.options[el.selectedIndex].text; - } else{ - textValue = el.value; - } - textNode = doc.createTextNode(textValue); - - valueWrap.appendChild(textNode); - body.appendChild(valueWrap); - - - renderText(el, textNode, stack); - body.removeChild(valueWrap); - - - - } - - - - - - function renderImage (ctx, image, sx, sy, sw, sh, dx, dy, dw, dh) { - ctx.drawImage( - image, - sx, //sx - sy, //sy - sw, //sw - sh, //sh - dx, //dx - dy, // dy - dw, //dw - dh //dh - ); - numDraws+=1; - - } - - - function renderBackgroundRepeat (ctx, image, x, y, width, height, elx, ely){ - var sourceX = 0, - sourceY=0; - if (elx-x>0){ - sourceX = elx-x; - } - - if (ely-y>0){ - sourceY = ely-y; - } - - renderImage( - ctx, - image, - sourceX, // source X - sourceY, // source Y - width-sourceX, // source Width - height-sourceY, // source Height - x+sourceX, // destination X - y+sourceY, // destination Y - width-sourceX, // destination width - height-sourceY // destination height - ); - } - - - function renderBackgroundRepeatY (ctx, image, bgp, x, y, w, h){ - - var height, - width = Math.min(image.width,w),bgy; - - bgp.top = bgp.top-Math.ceil(bgp.top/image.height)*image.height; - - - for(bgy=(y+bgp.top);bgyh+y){ - height = (h+y)-bgy; - }else{ - height = image.height; - } - renderBackgroundRepeat(ctx,image,x+bgp.left,bgy,width,height,x,y); - - bgy = Math.floor(bgy+image.height); - - } - } - - function renderBackgroundRepeatX(ctx, image, bgp, x, y, w, h){ - - var height = Math.min(image.height,h), - width,bgx; - - - bgp.left = bgp.left-Math.ceil(bgp.left/image.width)*image.width; - - - for (bgx=(x+bgp.left);bgxw+x){ - width = (w+x)-bgx; - }else{ - width = image.width; - } - - renderBackgroundRepeat(ctx,image,bgx,(y+bgp.top),width,height,x,y); - - bgx = Math.floor(bgx+image.width); - - - } - } - - function renderBackground(el,bounds,ctx){ - - // TODO add support for multi background-images - var background_image = getCSS(el, "backgroundImage"), - background_repeat = getCSS(el, "backgroundRepeat").split(",")[0], - image, - bgp, - bgy, - bgw, - bgsx, - bgsy, - bgdx, - bgdy, - bgh, - h, - height, - add; - - // if (typeof background_image !== "undefined" && /^(1|none)$/.test(background_image) === false && /^(-webkit|-moz|linear-gradient|-o-)/.test(background_image)===false){ - - if ( !/data:image\/.*;base64,/i.test(background_image) && !/^(-webkit|-moz|linear-gradient|-o-)/.test(background_image) ) { - background_image = background_image.split(",")[0]; - } - - if ( typeof background_image !== "undefined" && /^(1|none)$/.test( background_image ) === false ) { - background_image = _html2canvas.Util.backgroundImage( background_image ); - image = loadImage( background_image ); - - - bgp = _html2canvas.Util.BackgroundPosition(el, bounds, image); - - // TODO add support for background-origin - if ( image ){ - switch ( background_repeat ) { - - case "repeat-x": - renderBackgroundRepeatX( ctx, image, bgp, bounds.left, bounds.top, bounds.width, bounds.height ); - break; - - case "repeat-y": - renderBackgroundRepeatY( ctx, image, bgp, bounds.left, bounds.top, bounds.width, bounds.height ); - break; - - case "no-repeat": - /* - this.drawBackgroundRepeat( - ctx, - image, - bgp.left+bounds.left, // sx - bgp.top+bounds.top, // sy - Math.min(bounds.width,image.width), - Math.min(bounds.height,image.height), - bounds.left, - bounds.top - );*/ - - - // console.log($(el).css('background-image')); - bgw = bounds.width - bgp.left; - bgh = bounds.height - bgp.top; - bgsx = bgp.left; - bgsy = bgp.top; - bgdx = bgp.left+bounds.left; - bgdy = bgp.top+bounds.top; - - // - // bgw = Math.min(bgw,image.width); - // bgh = Math.min(bgh,image.height); - - if (bgsx<0){ - bgsx = Math.abs(bgsx); - bgdx += bgsx; - bgw = Math.min(bounds.width,image.width-bgsx); - }else{ - bgw = Math.min(bgw,image.width); - bgsx = 0; - } - - if (bgsy<0){ - bgsy = Math.abs(bgsy); - bgdy += bgsy; - // bgh = bgh-bgsy; - bgh = Math.min(bounds.height,image.height-bgsy); - }else{ - bgh = Math.min(bgh,image.height); - bgsy = 0; - } - - - if (bgh>0 && bgw > 0){ - renderImage( - ctx, - image, - bgsx, // source X : 0 - bgsy, // source Y : 1695 - bgw, // source Width : 18 - bgh, // source Height : 1677 - bgdx, // destination X :906 - bgdy, // destination Y : 1020 - bgw, // destination width : 18 - bgh // destination height : 1677 - ); - - } - break; - default: - - - - bgp.top = bgp.top-Math.ceil(bgp.top/image.height)*image.height; - - - for(bgy=(bounds.top+bgp.top);bgyh+bgy){ - height = (h+bgy)-bgy; - }else{ - height = image.height; - } - // console.log(height); - - if (bgy0){ - bgp.top += add; - } - bgy = Math.floor(bgy+image.height)-add; - } - break; - - - } - }else{ - h2clog("html2canvas: Error loading background:" + background_image); - //console.log(images); - } - - } - } - - - - function renderElement(el, parentStack){ - - var bounds = _html2canvas.Util.Bounds(el), - x = bounds.left, - y = bounds.top, - w = bounds.width, - h = bounds.height, - image, - bgcolor = getCSS(el, "backgroundColor"), - cssPosition = getCSS(el, "position"), - zindex, - opacity = getCSS(el, "opacity"), - stack, - stackLength, - borders, - ctx, - bgbounds, - imgSrc, - paddingLeft, - paddingTop, - paddingRight, - paddingBottom; - - if (!parentStack){ - docDim = docSize(); - parentStack = { - opacity: 1 - }; - }else{ - docDim = {}; - } - - - //var zindex = this.formatZ(this.getCSS(el,"zIndex"),cssPosition,parentStack.zIndex,el.parentNode); - - zindex = setZ( getCSS( el, "zIndex"), parentStack.zIndex ); - - - - stack = { - ctx: h2cRenderContext( docDim.width || w , docDim.height || h ), - zIndex: zindex, - opacity: opacity * parentStack.opacity, - cssPosition: cssPosition - }; - - - - // TODO correct overflow for absolute content residing under a static position - - if (parentStack.clip){ - stack.clip = _html2canvas.Util.Extend( {}, parentStack.clip ); - //stack.clip = parentStack.clip; - // stack.clip.height = stack.clip.height - parentStack.borders[2].width; - } - - - if ( options.useOverflow === true && /(hidden|scroll|auto)/.test(getCSS(el, "overflow")) === true && /(BODY)/i.test(el.nodeName) === false ){ - if (stack.clip){ - stack.clip = clipBounds(stack.clip, bounds); - }else{ - stack.clip = bounds; - } - } - - - stackLength = zindex.children.push(stack); - - ctx = zindex.children[stackLength-1].ctx; - - ctx.setVariable("globalAlpha", stack.opacity); - - // draw element borders - borders = renderBorders(el, ctx, bounds, false); - stack.borders = borders; - - - // let's modify clip area for child elements, so borders dont get overwritten - - /* - if (stack.clip){ - stack.clip.width = stack.clip.width-(borders[1].width); - stack.clip.height = stack.clip.height-(borders[2].width); - } - */ - if (ignoreElementsRegExp.test(el.nodeName) && options.iframeDefault !== "transparent"){ - if (options.iframeDefault === "default"){ - bgcolor = "#efefef"; - }else{ - bgcolor = options.iframeDefault; - } - } - - // draw base element bgcolor - - bgbounds = { - left: x + borders[3].width, - top: y + borders[0].width, - width: w - (borders[1].width + borders[3].width), - height: h - (borders[0].width + borders[2].width) - }; - - //if (this.withinBounds(stack.clip,bgbounds)){ - - if (stack.clip){ - bgbounds = clipBounds(bgbounds, stack.clip); - - //} - - } - - - if (bgbounds.height > 0 && bgbounds.width > 0){ - renderRect( - ctx, - bgbounds.left, - bgbounds.top, - bgbounds.width, - bgbounds.height, - bgcolor - ); - - renderBackground(el, bgbounds, ctx); - } - - switch(el.nodeName){ - case "IMG": - imgSrc = el.getAttribute('src'); - image = loadImage(imgSrc); - if (image){ - - paddingLeft = getCSSInt(el, 'paddingLeft'); - paddingTop = getCSSInt(el, 'paddingTop'); - paddingRight = getCSSInt(el, 'paddingRight'); - paddingBottom = getCSSInt(el, 'paddingBottom'); - - - renderImage( - ctx, - image, - 0, //sx - 0, //sy - image.width, //sw - image.height, //sh - x + paddingLeft + borders[3].width, //dx - y + paddingTop + borders[0].width, // dy - bounds.width - (borders[1].width + borders[3].width + paddingLeft + paddingRight), //dw - bounds.height - (borders[0].width + borders[2].width + paddingTop + paddingBottom) //dh - ); - - }else{ - h2clog("html2canvas: Error loading :" + imgSrc); - } - break; - case "INPUT": - // TODO add all relevant type's, i.e. HTML5 new stuff - // todo add support for placeholder attribute for browsers which support it - if (/^(text|url|email|submit|button|reset)$/.test(el.type) && el.value.length > 0){ - - renderFormValue(el, bounds, stack); - - - /* - this just doesn't work well enough - - this.newText(el,{ - nodeValue:el.value, - splitText: function(){ - return this; - }, - formValue:true - },stack); - */ - } - break; - case "TEXTAREA": - if (el.value.length > 0){ - renderFormValue(el, bounds, stack); - } - break; - case "SELECT": - if (el.options.length > 0){ - renderFormValue(el, bounds, stack); - } - break; - case "LI": - renderListItem(el, stack, bgbounds); - break; - case "CANVAS": - paddingLeft = getCSSInt(el, 'paddingLeft'); - paddingTop = getCSSInt(el, 'paddingTop'); - paddingRight = getCSSInt(el, 'paddingRight'); - paddingBottom = getCSSInt(el, 'paddingBottom'); - renderImage( - ctx, - el, - 0, //sx - 0, //sy - el.width, //sw - el.height, //sh - x + paddingLeft + borders[3].width, //dx - y + paddingTop + borders[0].width, // dy - bounds.width - (borders[1].width + borders[3].width + paddingLeft + paddingRight), //dw - bounds.height - (borders[0].width + borders[2].width + paddingTop + paddingBottom) //dh - ); - break; - } - - return zindex.children[stackLength - 1]; - } - - - - function parseElement (el, stack) { - - // skip hidden elements and their children - if (getCSS(el, 'display') !== "none" && getCSS(el, 'visibility') !== "hidden") { - - stack = renderElement(el, stack) || stack; - - ctx = stack.ctx; - - if ( !ignoreElementsRegExp.test( el.nodeName ) ) { - var elementChildren = _html2canvas.Util.Children( el ), - i, - node, - childrenLen; - for (i = 0, childrenLen = elementChildren.length; i < childrenLen; i+=1) { - node = elementChildren[i]; - - if ( node.nodeType === 1 ) { - parseElement(node, stack); - }else if ( node.nodeType === 3 ) { - renderText(el, node, stack); - } - - } - - } - } - } - - stack = renderElement(element, null); - - /* - SVG powered HTML rendering, non-tainted canvas available from FF 11+ onwards - */ - - if ( support.svgRendering ) { - (function( body ){ - var img = new Image(), - size = docSize(), - html = ""; - - function parseDOM( el ) { - var children = _html2canvas.Util.Children( el ), - len = children.length, - attr, - a, - alen, - elm, - i; - for ( i = 0; i < len; i+=1 ) { - elm = children[ i ]; - if ( elm.nodeType === 3 ) { - // Text node - - html += elm.nodeValue.replace(/\/g,">"); - } else if ( elm.nodeType === 1 ) { - // Element - if ( !/^(script|meta|title)$/.test(elm.nodeName.toLowerCase()) ) { - - html += "<" + elm.nodeName.toLowerCase(); - - // add attributes - if ( elm.hasAttributes() ) { - attr = elm.attributes; - alen = attr.length; - for ( a = 0; a < alen; a+=1 ) { - html += " " + attr[ a ].name + '="' + attr[ a ].value + '"'; - } - } - - - html += '>'; - - parseDOM( elm ); - - - html += ""; - } - } - - } - - } - - parseDOM( body ); - img.src = [ - "data:image/svg+xml,", - "", - "", - "", - html.replace(/\#/g,"%23"), - "", - "", - "" - ].join(""); - - - - - img.onload = function() { - stack.svgRender = img; - }; - - })( document.documentElement ); - - } - - - // parse every child element - for (i = 0, children = element.children, childrenLen = children.length; i < childrenLen; i+=1){ - parseElement(children[i], stack); - } - - - stack.backgroundColor = getCSS( document.documentElement, "backgroundColor" ); - - return stack; - -}; - -function h2czContext(zindex) { - return { - zindex: zindex, - children: [] - }; -} -/* - html2canvas v0.33 - Copyright (c) 2011 Niklas von Hertzen. All rights reserved. - http://www.twitter.com/niklasvh - - Released under MIT License -*/ - -_html2canvas.Preload = function( options ) { - - var images = { - numLoaded: 0, // also failed are counted here - numFailed: 0, - numTotal: 0, - cleanupDone: false - }, - pageOrigin, - methods, - i, - count = 0, - element = options.elements[0] || document.body, - doc = element.ownerDocument, - 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; - pageOrigin = link.protocol + link.host; - - - - - - - function isSameOrigin(url){ - link.href = url; - link.href = link.href; // YES, BELIEVE IT OR NOT, that is required for IE9 - http://jsfiddle.net/niklasvh/2e48b/ - var origin = link.protocol + link.host; - return (origin === pageOrigin); - } - - function start(){ - h2clog("html2canvas: start: images: " + images.numLoaded + " / " + images.numTotal + " (failed: " + images.numFailed + ")"); - if (!images.firstRun && images.numLoaded >= images.numTotal){ - h2clog("Finished loading images: # " + images.numTotal + " (failed: " + images.numFailed + ")"); - - if (typeof options.complete === "function"){ - options.complete(images); - } - - } - } - - // TODO modify proxy to serve images with CORS enabled, where available - function proxyGetImage(url, img, imageObj){ - var callback_name, - scriptUrl = options.proxy, - script; - - link.href = url; - url = link.href; // work around for pages with base href="" set - WARNING: this may change the url - - callback_name = 'html2canvas_' + (count++); - imageObj.callbackname = callback_name; - - if (scriptUrl.indexOf("?") > -1) { - scriptUrl += "&"; - } else { - scriptUrl += "?"; - } - scriptUrl += 'url=' + encodeURIComponent(url) + '&callback=' + callback_name; - script = doc.createElement("script"); - - window[callback_name] = function(a){ - if (a.substring(0,6) === "error:"){ - imageObj.succeeded = false; - images.numLoaded++; - images.numFailed++; - start(); - } else { - setImageLoadHandlers(img, imageObj); - img.src = a; - } - window[callback_name] = undefined; // to work with IE<9 // NOTE: that the undefined callback property-name still exists on the window object (for IE<9) - try { - delete window[callback_name]; // for all browser that support this - } catch(ex) {} - script.parentNode.removeChild(script); - script = null; - delete imageObj.script; - delete imageObj.callbackname; - }; - - script.setAttribute("type", "text/javascript"); - script.setAttribute("src", scriptUrl); - imageObj.script = script; - window.document.body.appendChild(script); - - } - - function getImages (el) { - - - - // if (!this.ignoreRe.test(el.nodeName)){ - // - - var contents = _html2canvas.Util.Children(el), - i, - contentsLen = contents.length, - background_image, - src, - img, - elNodeType = false; - - for (i = 0; i < contentsLen; i+=1 ){ - // var ignRe = new RegExp("("+this.ignoreElements+")"); - // if (!ignRe.test(element.nodeName)){ - getImages(contents[i]); - // } - } - - // } - try { - elNodeType = el.nodeType; - } catch (ex) { - elNodeType = false; - h2clog("html2canvas: failed to access some element's nodeType - Exception: " + ex.message); - } - - if (elNodeType === 1 || elNodeType === undefined){ - - // opera throws exception on external-content.html - try { - background_image = _html2canvas.Util.getCSS(el, 'backgroundImage'); - }catch(e) { - h2clog("html2canvas: failed to get background-image - Exception: " + e.message); - } - if ( background_image && background_image !== "1" && background_image !== "none" ) { - - // TODO add multi image background support - - if (/^(-webkit|-o|-moz|-ms|linear)-/.test( background_image )) { - // if (background_image.substring(0,7) === "-webkit" || background_image.substring(0,3) === "-o-" || background_image.substring(0,4) === "-moz") { - - img = _html2canvas.Generate.Gradient( background_image, _html2canvas.Util.Bounds( el ) ); - - if ( img !== undefined ){ - images[background_image] = { - img: img, - succeeded: true - }; - images.numTotal++; - images.numLoaded++; - start(); - - } - - } else { - src = _html2canvas.Util.backgroundImage(background_image.match(/data:image\/.*;base64,/i) ? background_image : background_image.split(",")[0]); - methods.loadImage(src); - } - - /* - if (background_image && background_image !== "1" && background_image !== "none" && background_image.substring(0,7) !== "-webkit" && background_image.substring(0,3)!== "-o-" && background_image.substring(0,4) !== "-moz"){ - // TODO add multi image background support - src = _html2canvas.Util.backgroundImage(background_image.split(",")[0]); - methods.loadImage(src); */ - } - } - } - - function setImageLoadHandlers(img, imageObj) { - img.onload = function() { - if ( imageObj.timer !== undefined ) { - // CORS succeeded - window.clearTimeout( imageObj.timer ); - } - - images.numLoaded++; - imageObj.succeeded = true; - img.onerror = img.onload = null; - 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; - img.onerror = img.onload = null; - start(); - - }; - - // TODO Opera has no load/error event for SVG images - - // Opera ninja onload's cached images - /* - window.setTimeout(function(){ - if ( img.width !== 0 && imageObj.succeeded === undefined ) { - img.onload(); - } - }, 100); // needs a reflow for base64 encoded images? interestingly timeout of 0 doesn't work but 1 does. - */ - } - - - methods = { - loadImage: function( src ) { - var img, imageObj; - if ( src && images[src] === undefined ) { - 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 ) || options.allowTaint === true ) { - imageObj = images[src] = { - img: img - }; - images.numTotal++; - setImageLoadHandlers(img, imageObj); - img.src = src; - } 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; - - // work around for https://bugs.webkit.org/show_bug.cgi?id=80028 - img.customComplete = function () { - if (!this.img.complete) { - this.timer = window.setTimeout(this.img.customComplete, 100); - } else { - this.img.onerror(); - } - }.bind(imageObj); - img.customComplete(); - - } else if ( options.proxy ) { - imageObj = images[src] = { - img: img - }; - images.numTotal++; - proxyGetImage( src, img, imageObj ); - } - } - - }, - cleanupDOM: function(cause) { - var img, src; - if (!images.cleanupDone) { - if (cause && typeof cause === "string") { - h2clog("html2canvas: Cleanup because: " + cause); - } else { - h2clog("html2canvas: Cleanup after timeout: " + options.timeout + " ms."); - } - - for (src in images) { - if (images.hasOwnProperty(src)) { - img = images[src]; - if (typeof img === "object" && img.callbackname && img.succeeded === undefined) { - // cancel proxy image request - window[img.callbackname] = undefined; // to work with IE<9 // NOTE: that the undefined callback property-name still exists on the window object (for IE<9) - try { - delete window[img.callbackname]; // for all browser that support this - } catch(ex) {} - if (img.script && img.script.parentNode) { - img.script.setAttribute("src", "about:blank"); // try to cancel running request - img.script.parentNode.removeChild(img.script); - } - images.numLoaded++; - images.numFailed++; - h2clog("html2canvas: Cleaned up failed img: '" + src + "' Steps: " + images.numLoaded + " / " + images.numTotal); - } - } - } - - // cancel any pending requests - if(window.stop !== undefined) { - window.stop(); - } else if(document.execCommand !== undefined) { - document.execCommand("Stop", false); - } - if (document.close !== undefined) { - document.close(); - } - images.cleanupDone = true; - if (!(cause && typeof cause === "string")) { - start(); - } - } - }, - renderingDone: function() { - if (timeoutTimer) { - window.clearTimeout(timeoutTimer); - } - } - - }; - - if (options.timeout > 0) { - timeoutTimer = window.setTimeout(methods.cleanupDOM, options.timeout); - } - h2clog('html2canvas: Preload starts: finding background-images'); - images.firstRun = true; - - getImages( element ); - - h2clog('html2canvas: Preload: Finding images'); - // load images - for (i = 0; i < imgLen; i+=1){ - methods.loadImage( domImages[i].getAttribute( "src" ) ); - } - - images.firstRun = false; - h2clog('html2canvas: Preload: Done.'); - if ( images.numTotal === images.numLoaded ) { - start(); - } - - return methods; - -}; - - - -/* - html2canvas v0.33 - Copyright (c) 2011 Niklas von Hertzen. All rights reserved. - http://www.twitter.com/niklasvh - - Released under MIT License -*/ -function h2cRenderContext(width, height) { - var storage = []; - return { - storage: storage, - width: width, - height: height, - fillRect: function () { - storage.push({ - type: "function", - name: "fillRect", - 'arguments': arguments - }); - }, - drawImage: function () { - storage.push({ - type: "function", - name: "drawImage", - 'arguments': arguments - }); - }, - fillText: function () { - storage.push({ - type: "function", - name: "fillText", - 'arguments': arguments - }); - }, - setVariable: function (variable, value) { - storage.push({ - type: "variable", - name: variable, - 'arguments': value - }); - } - }; -} -/* - html2canvas v0.33 - Copyright (c) 2011 Niklas von Hertzen. All rights reserved. - http://www.twitter.com/niklasvh - - Released under MIT License -*/ -_html2canvas.Renderer = function(parseQueue, options){ - - - var queue = []; - - function sortZ(zStack){ - var subStacks = [], - stackValues = [], - zStackChildren = zStack.children, - s, - i, - stackLen, - zValue, - zLen, - stackChild, - b, - subStackLen; - - - for (s = 0, zLen = zStackChildren.length; s < zLen; s+=1){ - - stackChild = zStackChildren[s]; - - if (stackChild.children && stackChild.children.length > 0){ - subStacks.push(stackChild); - stackValues.push(stackChild.zindex); - }else{ - queue.push(stackChild); - } - - } - - stackValues.sort(function(a, b) { - return a - b; - }); - - for (i = 0, stackLen = stackValues.length; i < stackLen; i+=1){ - zValue = stackValues[i]; - for (b = 0, subStackLen = subStacks.length; b <= subStackLen; b+=1){ - - if (subStacks[b].zindex === zValue){ - stackChild = subStacks.splice(b, 1); - sortZ(stackChild[0]); - break; - - } - } - } - - } - - - sortZ(parseQueue.zIndex); - if ( typeof options._renderer._create !== "function" ) { - throw new Error("Invalid renderer defined"); - } - return options._renderer._create( parseQueue, options, document, queue, _html2canvas ); - -}; -/* - html2canvas v0.33 - Copyright (c) 2011 Niklas von Hertzen. All rights reserved. - http://www.twitter.com/niklasvh - - Released under MIT License -*/ - - -html2canvas = function( elements, opts ) { - - var queue, - canvas, - options = { - // general - logging: false, - elements: elements, - - // preload options - proxy: "http://html2canvas.appspot.com/", - 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 - - // parse options - svgRendering: false, // use svg powered rendering where available (FF11+) - iframeDefault: "default", - ignoreElements: "IFRAME|OBJECT|PARAM", - useOverflow: true, - letterRendering: false, - - // render options - - flashcanvas: undefined, // path to flashcanvas - width: null, - height: null, - taintTest: true, // do a taint test with all images before applying to canvas - renderer: "Canvas" - }, renderer; - - options = _html2canvas.Util.Extend(opts, options); - - if (typeof options.renderer === "string" && _html2canvas.Renderer[options.renderer] !== undefined) { - options._renderer = _html2canvas.Renderer[options.renderer]( options ); - } else if (typeof options.renderer === "function") { - options._renderer = options.renderer( options ); - } else { - throw("Unknown renderer"); - } - - _html2canvas.logging = options.logging; - options.complete = function( images ) { - - if (typeof options.onpreloaded === "function") { - if ( options.onpreloaded( images ) === false ) { - return; - } - } - queue = _html2canvas.Parse( images, options ); - - if (typeof options.onparsed === "function") { - if ( options.onparsed( queue ) === false ) { - return; - } - } - - canvas = _html2canvas.Renderer( queue, options ); - - if (typeof options.onrendered === "function") { - options.onrendered( canvas ); - } - - - }; - - // for pages without images, we still want this to be async, i.e. return methods before executing - window.setTimeout( function(){ - _html2canvas.Preload( options ); - }, 0 ); - - return { - render: function( queue, opts ) { - return _html2canvas.Renderer( queue, _html2canvas.Util.Extend(opts, options) ); - }, - parse: function( images, opts ) { - return _html2canvas.Parse( images, _html2canvas.Util.Extend(opts, options) ); - }, - preload: function( opts ) { - return _html2canvas.Preload( _html2canvas.Util.Extend(opts, options) ); - }, - log: h2clog - }; -}; - -html2canvas.log = h2clog; // for renderers -html2canvas.Renderer = { - Canvas: undefined // We are assuming this will be used -}; -/* - html2canvas v0.33 - Copyright (c) 2011 Niklas von Hertzen. All rights reserved. - http://www.twitter.com/niklasvh - - Released under MIT License -*/ - - -_html2canvas.Renderer.Canvas = function( options ) { - - options = options || {}; - - var doc = document, - canvas = options.canvas || doc.createElement('canvas'), - usingFlashcanvas = false, - _createCalled = false, - canvasReadyToDraw = false, - methods, - flashMaxSize = 2880; // flash bitmap limited to 2880x2880px // http://stackoverflow.com/questions/2033792/argumenterror-error-2015-invalid-bitmapdata - - - if (canvas.getContext){ - h2clog("html2canvas: Renderer: using canvas renderer"); - canvasReadyToDraw = true; - } else if ( options.flashcanvas !== undefined ){ - usingFlashcanvas = true; - h2clog("html2canvas: Renderer: canvas not available, using flashcanvas"); - var script = doc.createElement("script"); - script.src = options.flashcanvas; - - script.onload = (function(script, func){ - var intervalFunc; - - if (script.onload === undefined) { - // IE lack of support for script onload - - if( script.onreadystatechange !== undefined ) { - - intervalFunc = function() { - if (script.readyState !== "loaded" && script.readyState !== "complete") { - window.setTimeout( intervalFunc, 250 ); - - } else { - // it is loaded - func(); - - } - - }; - - window.setTimeout( intervalFunc, 250 ); - - } else { - h2clog("html2canvas: Renderer: Can't track when flashcanvas is loaded"); - } - - } else { - return func; - } - - })(script, function(){ - - if (typeof window.FlashCanvas !== "undefined") { - h2clog("html2canvas: Renderer: Flashcanvas initialized"); - window.FlashCanvas.initElement( canvas ); - - canvasReadyToDraw = true; - if ( _createCalled !== false ) { - methods._create.apply( null, _createCalled ); - } - } - }); - - doc.body.appendChild( script ); - - } - - methods = { - _create: function( zStack, options, doc, queue, _html2canvas ) { - - if ( !canvasReadyToDraw ) { - _createCalled = arguments; - return canvas; - } - - var ctx = canvas.getContext("2d"), - storageContext, - i, - queueLen, - a, - newCanvas, - bounds, - testCanvas = document.createElement("canvas"), - hasCTX = ( testCanvas.getContext !== undefined ), - storageLen, - renderItem, - testctx = ( hasCTX ) ? testCanvas.getContext("2d") : {}, - safeImages = [], - fstyle; - - canvas.width = canvas.style.width = (!usingFlashcanvas) ? options.width || zStack.ctx.width : Math.min(flashMaxSize, (options.width || zStack.ctx.width) ); - canvas.height = canvas.style.height = (!usingFlashcanvas) ? options.height || zStack.ctx.height : Math.min(flashMaxSize, (options.height || zStack.ctx.height) ); - - fstyle = ctx.fillStyle; - ctx.fillStyle = zStack.backgroundColor; - ctx.fillRect(0, 0, canvas.width, canvas.height); - ctx.fillStyle = fstyle; - - if ( options.svgRendering && zStack.svgRender !== undefined ) { - // TODO: enable async rendering to support this - ctx.drawImage( zStack.svgRender, 0, 0 ); - } else { - for ( i = 0, queueLen = queue.length; i < queueLen; i+=1 ) { - - storageContext = queue.splice(0, 1)[0]; - storageContext.canvasPosition = storageContext.canvasPosition || {}; - - //this.canvasRenderContext(storageContext,parentctx); - - // set common settings for canvas - ctx.textBaseline = "bottom"; - - if (storageContext.clip){ - ctx.save(); - ctx.beginPath(); - // console.log(storageContext); - ctx.rect(storageContext.clip.left, storageContext.clip.top, storageContext.clip.width, storageContext.clip.height); - ctx.clip(); - - } - - if (storageContext.ctx.storage){ - - for (a = 0, storageLen = storageContext.ctx.storage.length; a < storageLen; a+=1){ - - renderItem = storageContext.ctx.storage[a]; - - - switch(renderItem.type){ - case "variable": - ctx[renderItem.name] = renderItem['arguments']; - break; - case "function": - if (renderItem.name === "fillRect") { - - if (!usingFlashcanvas || renderItem['arguments'][0] + renderItem['arguments'][2] < flashMaxSize && renderItem['arguments'][1] + renderItem['arguments'][3] < flashMaxSize) { - ctx.fillRect.apply( ctx, renderItem['arguments'] ); - } - }else if(renderItem.name === "fillText") { - if (!usingFlashcanvas || renderItem['arguments'][1] < flashMaxSize && renderItem['arguments'][2] < flashMaxSize) { - ctx.fillText.apply( ctx, renderItem['arguments'] ); - } - }else if(renderItem.name === "drawImage") { - - if (renderItem['arguments'][8] > 0 && renderItem['arguments'][7]){ - if ( hasCTX && options.taintTest ) { - if ( safeImages.indexOf( renderItem['arguments'][ 0 ].src ) === -1 ) { - testctx.drawImage( renderItem['arguments'][ 0 ], 0, 0 ); - try { - testctx.getImageData( 0, 0, 1, 1 ); - } catch(e) { - testCanvas = doc.createElement("canvas"); - testctx = testCanvas.getContext("2d"); - continue; - } - - safeImages.push( renderItem['arguments'][ 0 ].src ); - - } - } - ctx.drawImage.apply( ctx, renderItem['arguments'] ); - } - } - - - break; - default: - - } - - } - - } - if (storageContext.clip){ - ctx.restore(); - } - - } - } - - h2clog("html2canvas: Renderer: Canvas renderer done - returning canvas obj"); - - queueLen = options.elements.length; - - if (queueLen === 1) { - if (typeof options.elements[ 0 ] === "object" && options.elements[ 0 ].nodeName !== "BODY" && usingFlashcanvas === false) { - // crop image to the bounds of selected (single) element - bounds = _html2canvas.Util.Bounds( options.elements[ 0 ] ); - newCanvas = doc.createElement('canvas'); - newCanvas.width = bounds.width; - newCanvas.height = bounds.height; - ctx = newCanvas.getContext("2d"); - - ctx.drawImage( canvas, bounds.left, bounds.top, bounds.width, bounds.height, 0, 0, bounds.width, bounds.height ); - canvas = null; - return newCanvas; - } - } /*else { - // TODO clip and resize multiple elements - - for ( i = 0; i < queueLen; i+=1 ) { - if (options.elements[ i ] instanceof Element) { - - } - - } - } - */ - - - - return canvas; - } - }; - - return methods; - -}; -/* - html2canvas v0.33 - Copyright (c) 2011 Niklas von Hertzen. All rights reserved. - http://www.twitter.com/niklasvh - - Released under MIT License -*/ - - -// WARNING THIS file is outdated, and hasn't been tested in quite a while - -_html2canvas.Renderer.SVG = function( options ) { - - options = options || {}; - - var doc = document, - svgNS = "http://www.w3.org/2000/svg", - svg = doc.createElementNS(svgNS, "svg"), - xlinkNS = "http://www.w3.org/1999/xlink", - defs = doc.createElementNS(svgNS, "defs"), - i, - a, - queueLen, - storageLen, - storageContext, - renderItem, - el, - settings = {}, - text, - fontStyle, - clipId = 0, - methods; - - - methods = { - _create: function( zStack, options, doc, queue, _html2canvas ) { - svg.setAttribute("version", "1.1"); - svg.setAttribute("baseProfile", "full"); - - svg.setAttribute("viewBox", "0 0 " + Math.max(zStack.ctx.width, options.width) + " " + Math.max(zStack.ctx.height, options.height)); - svg.setAttribute("width", Math.max(zStack.ctx.width, options.width) + "px"); - svg.setAttribute("height", Math.max(zStack.ctx.height, options.height) + "px"); - svg.setAttribute("preserveAspectRatio", "none"); - svg.appendChild(defs); - - - - for (i = 0, queueLen = queue.length; i < queueLen; i+=1){ - - storageContext = queue.splice(0, 1)[0]; - storageContext.canvasPosition = storageContext.canvasPosition || {}; - - //this.canvasRenderContext(storageContext,parentctx); - - - /* - if (storageContext.clip){ - ctx.save(); - ctx.beginPath(); - // console.log(storageContext); - ctx.rect(storageContext.clip.left, storageContext.clip.top, storageContext.clip.width, storageContext.clip.height); - ctx.clip(); - - }*/ - - if (storageContext.ctx.storage){ - - for (a = 0, storageLen = storageContext.ctx.storage.length; a < storageLen; a+=1){ - - renderItem = storageContext.ctx.storage[a]; - - - - switch(renderItem.type){ - case "variable": - settings[renderItem.name] = renderItem['arguments']; - break; - case "function": - if (renderItem.name === "fillRect") { - - el = doc.createElementNS(svgNS, "rect"); - el.setAttribute("x", renderItem['arguments'][0]); - el.setAttribute("y", renderItem['arguments'][1]); - el.setAttribute("width", renderItem['arguments'][2]); - el.setAttribute("height", renderItem['arguments'][3]); - el.setAttribute("fill", settings.fillStyle); - svg.appendChild(el); - - } else if(renderItem.name === "fillText") { - el = doc.createElementNS(svgNS, "text"); - - fontStyle = settings.font.split(" "); - - el.style.fontVariant = fontStyle.splice(0, 1)[0]; - el.style.fontWeight = fontStyle.splice(0, 1)[0]; - el.style.fontStyle = fontStyle.splice(0, 1)[0]; - el.style.fontSize = fontStyle.splice(0, 1)[0]; - - el.setAttribute("x", renderItem['arguments'][1]); - el.setAttribute("y", renderItem['arguments'][2] - (parseInt(el.style.fontSize, 10) + 3)); - - el.setAttribute("fill", settings.fillStyle); - - - - - // TODO get proper baseline - el.style.dominantBaseline = "text-before-edge"; - el.style.fontFamily = fontStyle.join(" "); - - text = doc.createTextNode(renderItem['arguments'][0]); - el.appendChild(text); - - - svg.appendChild(el); - - - - } else if(renderItem.name === "drawImage") { - - if (renderItem['arguments'][8] > 0 && renderItem['arguments'][7]){ - - // TODO check whether even any clipping is necessary for this particular image - el = doc.createElementNS(svgNS, "clipPath"); - el.setAttribute("id", "clipId" + clipId); - - text = doc.createElementNS(svgNS, "rect"); - text.setAttribute("x", renderItem['arguments'][5] ); - text.setAttribute("y", renderItem['arguments'][6]); - - text.setAttribute("width", renderItem['arguments'][3]); - text.setAttribute("height", renderItem['arguments'][4]); - el.appendChild(text); - defs.appendChild(el); - - el = doc.createElementNS(svgNS, "image"); - el.setAttributeNS(xlinkNS, "xlink:href", renderItem['arguments'][0].src); - el.setAttribute("width", renderItem['arguments'][7]); - el.setAttribute("height", renderItem['arguments'][8]); - el.setAttribute("x", renderItem['arguments'][5]); - el.setAttribute("y", renderItem['arguments'][6]); - el.setAttribute("clip-path", "url(#clipId" + clipId + ")"); - // el.setAttribute("xlink:href", ); - - - el.setAttribute("preserveAspectRatio", "none"); - - svg.appendChild(el); - - - clipId += 1; - /* - ctx.drawImage( - renderItem['arguments'][0], - renderItem['arguments'][1], - renderItem['arguments'][2], - renderItem['arguments'][3], - renderItem['arguments'][4], - renderItem['arguments'][5], - renderItem['arguments'][6], - renderItem['arguments'][7], - renderItem['arguments'][8] - ); - */ - } - } - - - - break; - default: - - } - - } - - } - /* - if (storageContext.clip){ - ctx.restore(); - } - */ - - - - } - - - - - - - - - - - h2clog("html2canvas: Renderer: SVG Renderer done - returning SVG DOM obj"); - - return svg; - } - }; - - return methods; - - -}; -window.html2canvas = html2canvas; -}(window, document)); diff --git a/build/jquery.plugin.html2canvas.js b/build/jquery.plugin.html2canvas.js deleted file mode 100644 index 3270bf1..0000000 --- a/build/jquery.plugin.html2canvas.js +++ /dev/null @@ -1,87 +0,0 @@ -/** - @license html2canvas v0.33 - Copyright (c) 2011 Niklas von Hertzen. All rights reserved. - http://www.twitter.com/niklasvh - - Released under MIT License - */ -/* - * jQuery helper plugin for examples and tests - */ -(function( $ ){ - $.fn.html2canvas = function(options) { - if (options && options.profile && window.console && window.console.profile) { - console.profile(); - } - var date = new Date(), - html2obj, - $message = null, - timeoutTimer = false, - timer = date.getTime(); - options = options || {}; - - options.onrendered = options.onrendered || function( canvas ) { - var $canvas = $(canvas), - finishTime = new Date(); - - if (options && options.profile && window.console && window.console.profileEnd) { - console.profileEnd(); - } - $canvas.css({ - position: 'absolute', - left: 0, - top: 0 - }).appendTo(document.body); - $canvas.siblings().toggle(); - - $(window).click(function(){ - $canvas.toggle().siblings().toggle(); - throwMessage("Canvas Render " + ($canvas.is(':visible') ? "visible" : "hidden")); - }); - throwMessage('Screenshot created in '+ ((finishTime.getTime()-timer)) + " ms
",4000); - - // test if canvas is read-able - try { - $canvas[0].toDataURL(); - } catch(e) { - if ($canvas[0].nodeName.toLowerCase() === "canvas") { - // TODO, maybe add a bit less offensive way to present this, but still something that can easily be noticed - alert("Canvas is tainted, unable to read data"); - } - } - }; - - html2obj = html2canvas(this, options); - - function throwMessage(msg,duration){ - window.clearTimeout(timeoutTimer); - timeoutTimer = window.setTimeout(function(){ - $message.fadeOut(function(){ - $message.remove(); - $message = null; - }); - },duration || 2000); - if ($message) - $message.remove(); - $message = $('
').html(msg).css({ - margin:0, - padding:10, - background: "#000", - opacity:0.7, - position:"fixed", - top:10, - right:10, - fontFamily: 'Tahoma', - color:'#fff', - fontSize:12, - borderRadius:12, - width:'auto', - height:'auto', - textAlign:'center', - textDecoration:'none', - display:'none' - }).appendTo(document.body).fadeIn(); - html2obj.log(msg); - } - }; -})( jQuery );