| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010 | 
							- /*
 
-   html2canvas 0.4.1 <http://html2canvas.hertzen.com>
 
-   Copyright (c) 2013 Niklas von Hertzen
 
-   Released under MIT License
 
- */
 
- (function(window, document, undefined){
 
- //"use strict";
 
- var _html2canvas = {},
 
- previousElement,
 
- computedCSS,
 
- html2canvas;
 
- _html2canvas.Util = {};
 
- _html2canvas.Util.log = function(a) {
 
-   if (_html2canvas.logging && window.console && window.console.log) {
 
-     window.console.log(a);
 
-   }
 
- };
 
- _html2canvas.Util.trimText = (function(isNative){
 
-   return function(input) {
 
-     return isNative ? isNative.apply(input) : ((input || '') + '').replace( /^\s+|\s+$/g , '' );
 
-   };
 
- })(String.prototype.trim);
 
- _html2canvas.Util.asFloat = function(v) {
 
-   return parseFloat(v);
 
- };
 
- (function() {
 
-   // TODO: support all possible length values
 
-   var TEXT_SHADOW_PROPERTY = /((rgba|rgb)\([^\)]+\)(\s-?\d+px){0,})/g;
 
-   var TEXT_SHADOW_VALUES = /(-?\d+px)|(#.+)|(rgb\(.+\))|(rgba\(.+\))/g;
 
-   _html2canvas.Util.parseTextShadows = function (value) {
 
-     if (!value || value === 'none') {
 
-       return [];
 
-     }
 
-     // find multiple shadow declarations
 
-     var shadows = value.match(TEXT_SHADOW_PROPERTY),
 
-       results = [];
 
-     for (var i = 0; shadows && (i < shadows.length); i++) {
 
-       var s = shadows[i].match(TEXT_SHADOW_VALUES);
 
-       results.push({
 
-         color: s[0],
 
-         offsetX: s[1] ? s[1].replace('px', '') : 0,
 
-         offsetY: s[2] ? s[2].replace('px', '') : 0,
 
-         blur: s[3] ? s[3].replace('px', '') : 0
 
-       });
 
-     }
 
-     return results;
 
-   };
 
- })();
 
- _html2canvas.Util.parseBackgroundImage = function (value) {
 
-     var whitespace = ' \r\n\t',
 
-         method, definition, prefix, prefix_i, block, results = [],
 
-         c, mode = 0, numParen = 0, quote, args;
 
-     var appendResult = function(){
 
-         if(method) {
 
-             if(definition.substr( 0, 1 ) === '"') {
 
-                 definition = definition.substr( 1, definition.length - 2 );
 
-             }
 
-             if(definition) {
 
-                 args.push(definition);
 
-             }
 
-             if(method.substr( 0, 1 ) === '-' &&
 
-                     (prefix_i = method.indexOf( '-', 1 ) + 1) > 0) {
 
-                 prefix = method.substr( 0, prefix_i);
 
-                 method = method.substr( prefix_i );
 
-             }
 
-             results.push({
 
-                 prefix: prefix,
 
-                 method: method.toLowerCase(),
 
-                 value: block,
 
-                 args: args
 
-             });
 
-         }
 
-         args = []; //for some odd reason, setting .length = 0 didn't work in safari
 
-         method =
 
-             prefix =
 
-             definition =
 
-             block = '';
 
-     };
 
-     appendResult();
 
-     for(var i = 0, ii = value.length; i<ii; i++) {
 
-         c = value[i];
 
-         if(mode === 0 && whitespace.indexOf( c ) > -1){
 
-             continue;
 
-         }
 
-         switch(c) {
 
-             case '"':
 
-                 if(!quote) {
 
-                     quote = c;
 
-                 }
 
-                 else if(quote === c) {
 
-                     quote = null;
 
-                 }
 
-                 break;
 
-             case '(':
 
-                 if(quote) { break; }
 
-                 else if(mode === 0) {
 
-                     mode = 1;
 
-                     block += c;
 
-                     continue;
 
-                 } else {
 
-                     numParen++;
 
-                 }
 
-                 break;
 
-             case ')':
 
-                 if(quote) { break; }
 
-                 else if(mode === 1) {
 
-                     if(numParen === 0) {
 
-                         mode = 0;
 
-                         block += c;
 
-                         appendResult();
 
-                         continue;
 
-                     } else {
 
-                         numParen--;
 
-                     }
 
-                 }
 
-                 break;
 
-             case ',':
 
-                 if(quote) { break; }
 
-                 else if(mode === 0) {
 
-                     appendResult();
 
-                     continue;
 
-                 }
 
-                 else if (mode === 1) {
 
-                     if(numParen === 0 && !method.match(/^url$/i)) {
 
-                         args.push(definition);
 
-                         definition = '';
 
-                         block += c;
 
-                         continue;
 
-                     }
 
-                 }
 
-                 break;
 
-         }
 
-         block += c;
 
-         if(mode === 0) { method += c; }
 
-         else { definition += c; }
 
-     }
 
-     appendResult();
 
-     return results;
 
- };
 
- _html2canvas.Util.Bounds = function (element) {
 
-   var clientRect, bounds = {};
 
-   if (element.getBoundingClientRect){
 
-     clientRect = element.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;
 
-     bounds.width = element.offsetWidth;
 
-     bounds.height = element.offsetHeight;
 
-   }
 
-   return bounds;
 
- };
 
- // TODO ideally, we'd want everything to go through this function instead of Util.Bounds,
 
- // but would require further work to calculate the correct positions for elements with offsetParents
 
- _html2canvas.Util.OffsetBounds = function (element) {
 
-   var parent = element.offsetParent ? _html2canvas.Util.OffsetBounds(element.offsetParent) : {top: 0, left: 0};
 
-   return {
 
-     top: element.offsetTop + parent.top,
 
-     bottom: element.offsetTop + element.offsetHeight + parent.top,
 
-     left: element.offsetLeft + parent.left,
 
-     width: element.offsetWidth,
 
-     height: element.offsetHeight
 
-   };
 
- };
 
- function toPX(element, attribute, value ) {
 
-     var rsLeft = element.runtimeStyle && element.runtimeStyle[attribute],
 
-         left,
 
-         style = element.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( value ) && /^-?\d/.test(value) ) {
 
-         // Remember the original values
 
-         left = style.left;
 
-         // Put in the new values to get a computed value out
 
-         if (rsLeft) {
 
-             element.runtimeStyle.left = element.currentStyle.left;
 
-         }
 
-         style.left = attribute === "fontSize" ? "1em" : (value || 0);
 
-         value = style.pixelLeft + "px";
 
-         // Revert the changed values
 
-         style.left = left;
 
-         if (rsLeft) {
 
-             element.runtimeStyle.left = rsLeft;
 
-         }
 
-     }
 
-     if (!/^(thin|medium|thick)$/i.test(value)) {
 
-         return Math.round(parseFloat(value)) + "px";
 
-     }
 
-     return value;
 
- }
 
- function asInt(val) {
 
-     return parseInt(val, 10);
 
- }
 
- function isPercentage(value) {
 
-   return value.toString().indexOf("%") !== -1;
 
- }
 
- function parseBackgroundSizePosition(value, element, attribute, index) {
 
-     value = (value || '').split(',');
 
-     value = value[index || 0] || value[0] || 'auto';
 
-     value = _html2canvas.Util.trimText(value).split(' ');
 
-     if(attribute === 'backgroundSize' && (value[0] && value[0].match(/^(cover|contain|auto)$/))) {
 
-         return value;
 
-     } else {
 
-         value[0] = (value[0].indexOf( "%" ) === -1) ? toPX(element, attribute + "X", value[0]) : value[0];
 
-         if(value[1] === undefined) {
 
-             if(attribute === 'backgroundSize') {
 
-                 value[1] = 'auto';
 
-                 return value;
 
-             } else {
 
-                 // IE 9 doesn't return double digit always
 
-                 value[1] = value[0];
 
-             }
 
-         }
 
-         value[1] = (value[1].indexOf("%") === -1) ? toPX(element, attribute + "Y", value[1]) : value[1];
 
-     }
 
-     return value;
 
- }
 
- _html2canvas.Util.getCSS = function (element, attribute, index) {
 
-     if (previousElement !== element) {
 
-       computedCSS = document.defaultView.getComputedStyle(element, null);
 
-     }
 
-     var value = computedCSS[attribute];
 
-     if (/^background(Size|Position)$/.test(attribute)) {
 
-         return parseBackgroundSizePosition(value, element, attribute, index);
 
-     } else if (/border(Top|Bottom)(Left|Right)Radius/.test(attribute)) {
 
-       var arr = value.split(" ");
 
-       if (arr.length <= 1) {
 
-           arr[1] = arr[0];
 
-       }
 
-       return arr.map(asInt);
 
-     }
 
-   return value;
 
- };
 
- _html2canvas.Util.resizeBounds = function( current_width, current_height, target_width, target_height, stretch_mode ){
 
-   var target_ratio = target_width / target_height,
 
-     current_ratio = current_width / current_height,
 
-     output_width, output_height;
 
-   if(!stretch_mode || stretch_mode === 'auto') {
 
-     output_width = target_width;
 
-     output_height = target_height;
 
-   } else if(target_ratio < current_ratio ^ stretch_mode === 'contain') {
 
-     output_height = target_height;
 
-     output_width = target_height * current_ratio;
 
-   } else {
 
-     output_width = target_width;
 
-     output_height = target_width / current_ratio;
 
-   }
 
-   return {
 
-     width: output_width,
 
-     height: output_height
 
-   };
 
- };
 
- _html2canvas.Util.BackgroundPosition = function(element, bounds, image, imageIndex, backgroundSize ) {
 
-     var backgroundPosition =  _html2canvas.Util.getCSS(element, 'backgroundPosition', imageIndex),
 
-         leftPosition,
 
-         topPosition;
 
-     if (backgroundPosition.length === 1){
 
-         backgroundPosition = [backgroundPosition[0], backgroundPosition[0]];
 
-     }
 
-     if (isPercentage(backgroundPosition[0])){
 
-         leftPosition = (bounds.width - (backgroundSize || image).width) * (parseFloat(backgroundPosition[0]) / 100);
 
-     } else {
 
-         leftPosition = parseInt(backgroundPosition[0], 10);
 
-     }
 
-     if (backgroundPosition[1] === 'auto') {
 
-         topPosition = leftPosition / image.width * image.height;
 
-     } else if (isPercentage(backgroundPosition[1])){
 
-         topPosition =  (bounds.height - (backgroundSize || image).height) * parseFloat(backgroundPosition[1]) / 100;
 
-     } else {
 
-         topPosition = parseInt(backgroundPosition[1], 10);
 
-     }
 
-     if (backgroundPosition[0] === 'auto') {
 
-         leftPosition = topPosition / image.height * image.width;
 
-     }
 
-     return {left: leftPosition, top: topPosition};
 
- };
 
- _html2canvas.Util.BackgroundSize = function(element, bounds, image, imageIndex) {
 
-   var backgroundSize =  _html2canvas.Util.getCSS(element, 'backgroundSize', imageIndex), width, height;
 
-   if (backgroundSize.length === 1) {
 
-     backgroundSize = [backgroundSize[0], backgroundSize[0]];
 
-   }
 
-   if (isPercentage(backgroundSize[0])) {
 
-     width = bounds.width * parseFloat(backgroundSize[0]) / 100;
 
-   } else if (/contain|cover/.test(backgroundSize[0])) {
 
-     return _html2canvas.Util.resizeBounds(image.width, image.height, bounds.width, bounds.height, backgroundSize[0]);
 
-   } else {
 
-     width = parseInt(backgroundSize[0], 10);
 
-   }
 
-   if (backgroundSize[0] === 'auto' && backgroundSize[1] === 'auto') {
 
-     height = image.height;
 
-   } else if (backgroundSize[1] === 'auto') {
 
-     height = width / image.width * image.height;
 
-   } else if (isPercentage(backgroundSize[1])) {
 
-     height =  bounds.height * parseFloat(backgroundSize[1]) / 100;
 
-   } else {
 
-     height = parseInt(backgroundSize[1], 10);
 
-   }
 
-   if (backgroundSize[0] === 'auto') {
 
-     width = height / image.height * image.width;
 
-   }
 
-   return {width: width, height: height};
 
- };
 
- _html2canvas.Util.BackgroundRepeat = function(element, imageIndex) {
 
-   var backgroundRepeat = _html2canvas.Util.getCSS(element, "backgroundRepeat").split(",").map(_html2canvas.Util.trimText);
 
-   return backgroundRepeat[imageIndex] || backgroundRepeat[0];
 
- };
 
- _html2canvas.Util.Extend = function (options, defaults) {
 
-   for (var key in options) {
 
-     if (options.hasOwnProperty(key)) {
 
-       defaults[key] = options[key];
 
-     }
 
-   }
 
-   return defaults;
 
- };
 
- /*
 
-  * Derived from jQuery.contents()
 
-  * Copyright 2010, John Resig
 
-  * Dual licensed under the MIT or GPL Version 2 licenses.
 
-  * http://jquery.org/license
 
-  */
 
- _html2canvas.Util.Children = function( elem ) {
 
-   var children;
 
-   try {
 
-     children = (elem.nodeName && elem.nodeName.toUpperCase() === "IFRAME") ? elem.contentDocument || elem.contentWindow.document : (function(array) {
 
-       var ret = [];
 
-       if (array !== null) {
 
-         (function(first, second ) {
 
-           var i = first.length,
 
-           j = 0;
 
-           if (typeof second.length === "number") {
 
-             for (var l = second.length; j < l; j++) {
 
-               first[i++] = second[j];
 
-             }
 
-           } else {
 
-             while (second[j] !== undefined) {
 
-               first[i++] = second[j++];
 
-             }
 
-           }
 
-           first.length = i;
 
-           return first;
 
-         })(ret, array);
 
-       }
 
-       return ret;
 
-     })(elem.childNodes);
 
-   } catch (ex) {
 
-     _html2canvas.Util.log("html2canvas.Util.Children failed with exception: " + ex.message);
 
-     children = [];
 
-   }
 
-   return children;
 
- };
 
- _html2canvas.Util.isTransparent = function(backgroundColor) {
 
-   return (!backgroundColor || backgroundColor === "transparent" || backgroundColor === "rgba(0, 0, 0, 0)");
 
- };
 
- _html2canvas.Util.Font = (function () {
 
-   var fontData = {};
 
-   return function(font, fontSize, doc) {
 
-     if (fontData[font + "-" + fontSize] !== undefined) {
 
-       return fontData[font + "-" + fontSize];
 
-     }
 
-     var container = doc.createElement('div'),
 
-     img = doc.createElement('img'),
 
-     span = doc.createElement('span'),
 
-     sampleText = 'Hidden Text',
 
-     baseline,
 
-     middle,
 
-     metricsObj;
 
-     container.style.visibility = "hidden";
 
-     container.style.fontFamily = font;
 
-     container.style.fontSize = fontSize;
 
-     container.style.margin = 0;
 
-     container.style.padding = 0;
 
-     doc.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(sampleText));
 
-     container.appendChild(span);
 
-     container.appendChild(img);
 
-     baseline = (img.offsetTop - span.offsetTop) + 1;
 
-     container.removeChild(span);
 
-     container.appendChild(doc.createTextNode(sampleText));
 
-     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;
 
-     doc.body.removeChild(container);
 
-     return metricsObj;
 
-   };
 
- })();
 
- (function(){
 
-   var Util = _html2canvas.Util,
 
-     Generate = {};
 
-   _html2canvas.Generate = 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)
 
-  */
 
-   Generate.parseGradient = function(css, bounds) {
 
-     var gradient, i, len = reGradients.length, m1, stop, m2, m2Len, step, m3, tl,tr,br,bl;
 
-     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 :(
 
-                 tl = Math.sqrt(Math.pow(gradient.cx, 2) + Math.pow(gradient.cy, 2));
 
-                 tr = Math.sqrt(Math.pow(gradient.cx, 2) + Math.pow(gradient.y1 - gradient.cy, 2));
 
-                 br = Math.sqrt(Math.pow(gradient.x1 - gradient.cx, 2) + Math.pow(gradient.y1 - gradient.cy, 2));
 
-                 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':
 
-                 tl = Math.sqrt(Math.pow(gradient.cx, 2) + Math.pow(gradient.cy, 2));
 
-                 tr = Math.sqrt(Math.pow(gradient.cx, 2) + Math.pow(gradient.y1 - gradient.cy, 2));
 
-                 br = Math.sqrt(Math.pow(gradient.x1 - gradient.cx, 2) + Math.pow(gradient.y1 - gradient.cy, 2));
 
-                 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;
 
-   };
 
-   function addScrollStops(grad) {
 
-     return function(colorStop) {
 
-       try {
 
-         grad.addColorStop(colorStop.stop, colorStop.color);
 
-       }
 
-       catch(e) {
 
-         Util.log(['failed to add color stop: ', e, '; tried to add: ', colorStop]);
 
-       }
 
-     };
 
-   }
 
-   Generate.Gradient = function(src, bounds) {
 
-     if(bounds.width === 0 || bounds.height === 0) {
 
-       return;
 
-     }
 
-     var canvas = document.createElement('canvas'),
 
-     ctx = canvas.getContext('2d'),
 
-     gradient, grad;
 
-     canvas.width = bounds.width;
 
-     canvas.height = bounds.height;
 
-     // TODO: add support for multi defined background gradients
 
-     gradient = _html2canvas.Generate.parseGradient(src, bounds);
 
-     if(gradient) {
 
-       switch(gradient.type) {
 
-         case 'linear':
 
-           grad = ctx.createLinearGradient(gradient.x0, gradient.y0, gradient.x1, gradient.y1);
 
-           gradient.colorStops.forEach(addScrollStops(grad));
 
-           ctx.fillStyle = grad;
 
-           ctx.fillRect(0, 0, bounds.width, bounds.height);
 
-           break;
 
-         case 'circle':
 
-           grad = ctx.createRadialGradient(gradient.cx, gradient.cy, 0, gradient.cx, gradient.cy, gradient.rx);
 
-           gradient.colorStops.forEach(addScrollStops(grad));
 
-           ctx.fillStyle = grad;
 
-           ctx.fillRect(0, 0, bounds.width, bounds.height);
 
-           break;
 
-         case 'ellipse':
 
-           var canvasRadial = document.createElement('canvas'),
 
-             ctxRadial = canvasRadial.getContext('2d'),
 
-             ri = Math.max(gradient.rx, gradient.ry),
 
-             di = ri * 2;
 
-           canvasRadial.width = canvasRadial.height = di;
 
-           grad = ctxRadial.createRadialGradient(gradient.rx, gradient.ry, 0, gradient.rx, gradient.ry, ri);
 
-           gradient.colorStops.forEach(addScrollStops(grad));
 
-           ctxRadial.fillStyle = grad;
 
-           ctxRadial.fillRect(0, 0, di, di);
 
-           ctx.fillStyle = gradient.colorStops[gradient.colorStops.length - 1].color;
 
-           ctx.fillRect(0, 0, canvas.width, canvas.height);
 
-           ctx.drawImage(canvasRadial, gradient.cx - gradient.rx, gradient.cy - gradient.ry, 2 * gradient.rx, 2 * gradient.ry);
 
-           break;
 
-       }
 
-     }
 
-     return canvas;
 
-   };
 
-   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;
 
-   };
 
-   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;
 
-   };
 
- })();
 
- function h2cRenderContext(width, height) {
 
-   var storage = [];
 
-   return {
 
-     storage: storage,
 
-     width: width,
 
-     height: height,
 
-     clip: function() {
 
-       storage.push({
 
-         type: "function",
 
-         name: "clip",
 
-         'arguments': arguments
 
-       });
 
-     },
 
-     translate: function() {
 
-       storage.push({
 
-         type: "function",
 
-         name: "translate",
 
-         'arguments': arguments
 
-       });
 
-     },
 
-     fill: function() {
 
-       storage.push({
 
-         type: "function",
 
-         name: "fill",
 
-         'arguments': arguments
 
-       });
 
-     },
 
-     save: function() {
 
-       storage.push({
 
-         type: "function",
 
-         name: "save",
 
-         'arguments': arguments
 
-       });
 
-     },
 
-     restore: function() {
 
-       storage.push({
 
-         type: "function",
 
-         name: "restore",
 
-         'arguments': arguments
 
-       });
 
-     },
 
-     fillRect: function () {
 
-       storage.push({
 
-         type: "function",
 
-         name: "fillRect",
 
-         'arguments': arguments
 
-       });
 
-     },
 
-     createPattern: function() {
 
-       storage.push({
 
-         type: "function",
 
-         name: "createPattern",
 
-         'arguments': arguments
 
-       });
 
-     },
 
-     drawShape: function() {
 
-       var shape = [];
 
-       storage.push({
 
-         type: "function",
 
-         name: "drawShape",
 
-         'arguments': shape
 
-       });
 
-       return {
 
-         moveTo: function() {
 
-           shape.push({
 
-             name: "moveTo",
 
-             'arguments': arguments
 
-           });
 
-         },
 
-         lineTo: function() {
 
-           shape.push({
 
-             name: "lineTo",
 
-             'arguments': arguments
 
-           });
 
-         },
 
-         arcTo: function() {
 
-           shape.push({
 
-             name: "arcTo",
 
-             'arguments': arguments
 
-           });
 
-         },
 
-         bezierCurveTo: function() {
 
-           shape.push({
 
-             name: "bezierCurveTo",
 
-             'arguments': arguments
 
-           });
 
-         },
 
-         quadraticCurveTo: function() {
 
-           shape.push({
 
-             name: "quadraticCurveTo",
 
-             '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
 
-       });
 
-       return value;
 
-     }
 
-   };
 
- }
 
- _html2canvas.Parse = function (images, options, cb) {
 
-   window.scroll(0,0);
 
-   var element = (( options.elements === undefined ) ? document.body : options.elements[0]), // select body by default
 
-   numDraws = 0,
 
-   doc = element.ownerDocument,
 
-   Util = _html2canvas.Util,
 
-   support = Util.Support(options, doc),
 
-   ignoreElementsRegExp = new RegExp("(" + options.ignoreElements + ")"),
 
-   body = doc.body,
 
-   getCSS = Util.getCSS,
 
-   pseudoHide = "___html2canvas___pseudoelement",
 
-   hidePseudoElementsStyles = doc.createElement('style');
 
-   hidePseudoElementsStyles.innerHTML = '.' + pseudoHide +
 
-   '-parent:before { content: "" !important; display: none !important; }' +
 
-   '.' + pseudoHide + '-parent:after { content: "" !important; display: none !important; }';
 
-   body.appendChild(hidePseudoElementsStyles);
 
-   images = images || {};
 
-   init();
 
-   function init() {
 
-     var background = getCSS(document.documentElement, "backgroundColor"),
 
-       transparentBackground = (Util.isTransparent(background) && element === document.body),
 
-       stack = renderElement(element, null, false, transparentBackground);
 
-     // create pseudo elements in a single pass to prevent synchronous layouts
 
-     addPseudoElements(element);
 
-     parseChildren(element, stack, function() {
 
-       if (transparentBackground) {
 
-         background = stack.backgroundColor;
 
-       }
 
-       removePseudoElements();
 
-       Util.log('Done parsing, moving to Render.');
 
-       cb({
 
-         backgroundColor: background,
 
-         stack: stack
 
-       });
 
-     });
 
-   }
 
-   // Given a root element, find all pseudo elements below, create elements mocking pseudo element styles
 
-   // so we can process them as normal elements, and hide the original pseudo elements so they don't interfere
 
-   // with layout.
 
-   function addPseudoElements(el) {
 
-     // These are done in discrete steps to prevent a relayout loop caused by addClass() invalidating
 
-     // layouts & getPseudoElement calling getComputedStyle.
 
-     var jobs = [], classes = [];
 
-     getPseudoElementClasses();
 
-     findPseudoElements(el);
 
-     runJobs();
 
-     function getPseudoElementClasses(){
 
-       var findPsuedoEls = /:before|:after/;
 
-       var sheets = document.styleSheets;
 
-       for (var i = 0, j = sheets.length; i < j; i++) {
 
-         try {
 
-           var rules = sheets[i].cssRules;
 
-           for (var k = 0, l = rules.length; k < l; k++) {
 
-             if(findPsuedoEls.test(rules[k].selectorText)) {
 
-               classes.push(rules[k].selectorText);
 
-             }
 
-           }
 
-         }
 
-         catch(e) { // will throw security exception for style sheets loaded from external domains
 
-         }
 
-       }
 
-       // Trim off the :after and :before (or ::after and ::before)
 
-       for (i = 0, j = classes.length; i < j; i++) {
 
-         classes[i] = classes[i].match(/(^[^:]*)/)[1];
 
-       }
 
-     }
 
-     // Using the list of elements we know how pseudo el styles, create fake pseudo elements.
 
-     function findPseudoElements(el) {
 
-       var els = document.querySelectorAll(classes.join(','));
 
-       for(var i = 0, j = els.length; i < j; i++) {
 
-         createPseudoElements(els[i]);
 
-       }
 
-     }
 
-     // Create pseudo elements & add them to a job queue.
 
-     function createPseudoElements(el) {
 
-       var before = getPseudoElement(el, ':before'),
 
-       after = getPseudoElement(el, ':after');
 
-       if(before) {
 
-         jobs.push({type: 'before', pseudo: before, el: el});
 
-       }
 
-       if (after) {
 
-         jobs.push({type: 'after', pseudo: after, el: el});
 
-       }
 
-     }
 
-     // Adds a class to the pseudo's parent to prevent the original before/after from messing
 
-     // with layouts.
 
-     // Execute the inserts & addClass() calls in a batch to prevent relayouts.
 
-     function runJobs() {
 
-       // Add Class
 
-       jobs.forEach(function(job){
 
-         addClass(job.el, pseudoHide + "-parent");
 
-       });
 
-       // Insert el
 
-       jobs.forEach(function(job){
 
-         if(job.type === 'before'){
 
-           job.el.insertBefore(job.pseudo, job.el.firstChild);
 
-         } else {
 
-           job.el.appendChild(job.pseudo);
 
-         }
 
-       });
 
-     }
 
-   }
 
-   // Delete our fake pseudo elements from the DOM. This will remove those actual elements
 
-   // and the classes on their parents that hide the actual pseudo elements.
 
-   // Note that NodeLists are 'live' collections so you can't use a for loop here. They are
 
-   // actually deleted from the NodeList after each iteration.
 
-   function removePseudoElements(){
 
-     // delete pseudo elements
 
-     body.removeChild(hidePseudoElementsStyles);
 
-     var pseudos = document.getElementsByClassName(pseudoHide + "-element");
 
-     while (pseudos.length) {
 
-       pseudos[0].parentNode.removeChild(pseudos[0]);
 
-     }
 
-     // Remove pseudo hiding classes
 
-     var parents = document.getElementsByClassName(pseudoHide + "-parent");
 
-     while(parents.length) {
 
-       removeClass(parents[0], pseudoHide + "-parent");
 
-     }
 
-   }
 
-   function addClass (el, className) {
 
-     if (el.classList) {
 
-       el.classList.add(className);
 
-     } else {
 
-       el.className = el.className + " " + className;
 
-     }
 
-   }
 
-   function removeClass (el, className) {
 
-     if (el.classList) {
 
-       el.classList.remove(className);
 
-     } else {
 
-       el.className = el.className.replace(className, "").trim();
 
-     }
 
-   }
 
-   function hasClass (el, className) {
 
-     return el.className.indexOf(className) > -1;
 
-   }
 
-   // Note that this doesn't work in < IE8, but we don't support that anyhow
 
-   function nodeListToArray (nodeList) {
 
-     return Array.prototype.slice.call(nodeList);
 
-   }
 
-   function documentWidth () {
 
-     return 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)
 
-       );
 
-   }
 
-   function documentHeight () {
 
-     return 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)
 
-       );
 
-   }
 
-   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
 
-   }
 
-   function renderRect (ctx, x, y, w, h, bgcolor) {
 
-     if (bgcolor !== "transparent"){
 
-       ctx.setVariable("fillStyle", bgcolor);
 
-       ctx.fillRect(x, y, w, h);
 
-       numDraws+=1;
 
-     }
 
-   }
 
-   function capitalize(m, p1, p2) {
 
-     if (m.length > 0) {
 
-       return p1 + p2.toUpperCase();
 
-     }
 
-   }
 
-   function textTransform (text, transform) {
 
-     switch(transform){
 
-       case "lowercase":
 
-         return text.toLowerCase();
 
-       case "capitalize":
 
-         return text.replace( /(^|\s|:|-|\(|\))([a-z])/g, capitalize);
 
-       case "uppercase":
 
-         return text.toUpperCase();
 
-       default:
 
-         return text;
 
-     }
 
-   }
 
-   function noLetterSpacing(letter_spacing) {
 
-     return (/^(normal|none|0px)$/.test(letter_spacing));
 
-   }
 
-   function drawText(currentText, x, y, ctx){
 
-     if (currentText !== null && Util.trimText(currentText).length > 0) {
 
-       ctx.fillText(currentText, x, y);
 
-       numDraws+=1;
 
-     }
 
-   }
 
-   function setTextVariables(ctx, el, text_decoration, color) {
 
-     var align = false,
 
-     bold = getCSS(el, "fontWeight"),
 
-     family = getCSS(el, "fontFamily"),
 
-     size = getCSS(el, "fontSize"),
 
-     shadows = Util.parseTextShadows(getCSS(el, "textShadow"));
 
-     switch(parseInt(bold, 10)){
 
-       case 401:
 
-         bold = "bold";
 
-         break;
 
-       case 400:
 
-         bold = "normal";
 
-         break;
 
-     }
 
-     ctx.setVariable("fillStyle", color);
 
-     ctx.setVariable("font", [getCSS(el, "fontStyle"), getCSS(el, "fontVariant"), bold, size, family].join(" "));
 
-     ctx.setVariable("textAlign", (align) ? "right" : "left");
 
-     if (shadows.length) {
 
-       // TODO: support multiple text shadows
 
-       // apply the first text shadow
 
-       ctx.setVariable("shadowColor", shadows[0].color);
 
-       ctx.setVariable("shadowOffsetX", shadows[0].offsetX);
 
-       ctx.setVariable("shadowOffsetY", shadows[0].offsetY);
 
-       ctx.setVariable("shadowBlur", shadows[0].blur);
 
-     }
 
-     if (text_decoration !== "none"){
 
-       return Util.Font(family, size, doc);
 
-     }
 
-   }
 
-   function renderTextDecoration(ctx, text_decoration, bounds, metrics, color) {
 
-     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, Math.round(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;
 
-     }
 
-   }
 
-   function getTextBounds(state, text, textDecoration, isLast, transform) {
 
-     var bounds;
 
-     if (support.rangeBounds && !transform) {
 
-       if (textDecoration !== "none" || Util.trimText(text).length !== 0) {
 
-         bounds = textRangeBounds(text, state.node, state.textOffset);
 
-       }
 
-       state.textOffset += text.length;
 
-     } else if (state.node && typeof state.node.nodeValue === "string" ){
 
-       var newTextNode = (isLast) ? state.node.splitText(text.length) : null;
 
-       bounds = textWrapperBounds(state.node, transform);
 
-       state.node = newTextNode;
 
-     }
 
-     return bounds;
 
-   }
 
-   function textRangeBounds(text, textNode, textOffset) {
 
-     var range = doc.createRange();
 
-     range.setStart(textNode, textOffset);
 
-     range.setEnd(textNode, textOffset + text.length);
 
-     return range.getBoundingClientRect();
 
-   }
 
-   function textWrapperBounds(oldTextNode, transform) {
 
-     var parent = oldTextNode.parentNode,
 
-     wrapElement = doc.createElement('wrapper'),
 
-     backupText = oldTextNode.cloneNode(true);
 
-     wrapElement.appendChild(oldTextNode.cloneNode(true));
 
-     parent.replaceChild(wrapElement, oldTextNode);
 
-     var bounds = transform ? Util.OffsetBounds(wrapElement) : Util.Bounds(wrapElement);
 
-     parent.replaceChild(backupText, wrapElement);
 
-     return bounds;
 
-   }
 
-   function renderText(el, textNode, stack) {
 
-     var ctx = stack.ctx,
 
-     color = getCSS(el, "color"),
 
-     textDecoration = getCSS(el, "textDecoration"),
 
-     textAlign = getCSS(el, "textAlign"),
 
-     metrics,
 
-     textList,
 
-     state = {
 
-       node: textNode,
 
-       textOffset: 0
 
-     };
 
-     if (Util.trimText(textNode.nodeValue).length > 0) {
 
-       textNode.nodeValue = textTransform(textNode.nodeValue, getCSS(el, "textTransform"));
 
-       textAlign = textAlign.replace(["-webkit-auto"],["auto"]);
 
-       textList = (!options.letterRendering && /^(left|right|justify|auto)$/.test(textAlign) && noLetterSpacing(getCSS(el, "letterSpacing"))) ?
 
-       textNode.nodeValue.split(/(\b| )/)
 
-       : textNode.nodeValue.split("");
 
-       metrics = setTextVariables(ctx, el, textDecoration, color);
 
-       if (options.chinese) {
 
-         textList.forEach(function(word, index) {
 
-           if (/.*[\u4E00-\u9FA5].*$/.test(word)) {
 
-             word = word.split("");
 
-             word.unshift(index, 1);
 
-             textList.splice.apply(textList, word);
 
-           }
 
-         });
 
-       }
 
-       textList.forEach(function(text, index) {
 
-         var bounds = getTextBounds(state, text, textDecoration, (index < textList.length - 1), stack.transform.matrix);
 
-         if (bounds) {
 
-           drawText(text, bounds.left, bounds.bottom, ctx);
 
-           renderTextDecoration(ctx, textDecoration, bounds, metrics, color);
 
-         }
 
-       });
 
-     }
 
-   }
 
-   function listPosition (element, val) {
 
-     var boundElement = doc.createElement( "boundelement" ),
 
-     originalType,
 
-     bounds;
 
-     boundElement.style.display = "inline";
 
-     originalType = element.style.listStyleType;
 
-     element.style.listStyleType = "none";
 
-     boundElement.appendChild(doc.createTextNode(val));
 
-     element.insertBefore(boundElement, element.firstChild);
 
-     bounds = Util.Bounds(boundElement);
 
-     element.removeChild(boundElement);
 
-     element.style.listStyleType = originalType;
 
-     return bounds;
 
-   }
 
-   function elementIndex(el) {
 
-     var i = -1,
 
-     count = 1,
 
-     childs = el.parentNode.childNodes;
 
-     if (el.parentNode) {
 
-       while(childs[++i] !== el) {
 
-         if (childs[i].nodeType === 1) {
 
-           count++;
 
-         }
 
-       }
 
-       return count;
 
-     } else {
 
-       return -1;
 
-     }
 
-   }
 
-   function listItemText(element, type) {
 
-     var currentIndex = elementIndex(element), text;
 
-     switch(type){
 
-       case "decimal":
 
-         text = currentIndex;
 
-         break;
 
-       case "decimal-leading-zero":
 
-         text = (currentIndex.toString().length === 1) ? currentIndex = "0" + currentIndex.toString() : 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;
 
-     }
 
-     return text + ". ";
 
-   }
 
-   function renderListItem(element, stack, elBounds) {
 
-     var x,
 
-     text,
 
-     ctx = stack.ctx,
 
-     type = getCSS(element, "listStyleType"),
 
-     listBounds;
 
-     if (/^(decimal|decimal-leading-zero|upper-alpha|upper-latin|upper-roman|lower-alpha|lower-greek|lower-latin|lower-roman)$/i.test(type)) {
 
-       text = listItemText(element, type);
 
-       listBounds = listPosition(element, text);
 
-       setTextVariables(ctx, element, "none", getCSS(element, "color"));
 
-       if (getCSS(element, "listStylePosition") === "inside") {
 
-         ctx.setVariable("textAlign", "left");
 
-         x = elBounds.left;
 
-       } else {
 
-         return;
 
-       }
 
-       drawText(text, x, listBounds.bottom, ctx);
 
-     }
 
-   }
 
-   function loadImage (src){
 
-     var img = images[src];
 
-     return (img && img.succeeded === true) ? img.img : 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(element, stack, parentStack){
 
-     var newContext,
 
-     isPositioned = stack.cssPosition !== 'static',
 
-     zIndex = isPositioned ? getCSS(element, 'zIndex') : 'auto',
 
-     opacity = getCSS(element, 'opacity'),
 
-     isFloated = getCSS(element, 'cssFloat') !== 'none';
 
-     // https://developer.mozilla.org/en-US/docs/Web/Guide/CSS/Understanding_z_index/The_stacking_context
 
-     // When a new stacking context should be created:
 
-     // the root element (HTML),
 
-     // positioned (absolutely or relatively) with a z-index value other than "auto",
 
-     // elements with an opacity value less than 1. (See the specification for opacity),
 
-     // on mobile WebKit and Chrome 22+, position: fixed always creates a new stacking context, even when z-index is "auto" (See this post)
 
-     stack.zIndex = newContext = h2czContext(zIndex);
 
-     newContext.isPositioned = isPositioned;
 
-     newContext.isFloated = isFloated;
 
-     newContext.opacity = opacity;
 
-     newContext.ownStacking = (zIndex !== 'auto' || opacity < 1);
 
-     newContext.depth = parentStack ? (parentStack.zIndex.depth + 1) : 0;
 
-     if (parentStack) {
 
-       parentStack.zIndex.children.push(stack);
 
-     }
 
-   }
 
-   function h2czContext(zindex) {
 
-     return {
 
-       depth: 0,
 
-       zindex: zindex,
 
-       children: []
 
-     };
 
-   }
 
-   function renderImage(ctx, element, image, bounds, borders) {
 
-     var paddingLeft = getCSSInt(element, 'paddingLeft'),
 
-     paddingTop = getCSSInt(element, 'paddingTop'),
 
-     paddingRight = getCSSInt(element, 'paddingRight'),
 
-     paddingBottom = getCSSInt(element, 'paddingBottom');
 
-     drawImage(
 
-       ctx,
 
-       image,
 
-       0, //sx
 
-       0, //sy
 
-       image.width, //sw
 
-       image.height, //sh
 
-       bounds.left + paddingLeft + borders[3].width, //dx
 
-       bounds.top + 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
 
-       );
 
-   }
 
-   function getBorderData(element) {
 
-     return ["Top", "Right", "Bottom", "Left"].map(function(side) {
 
-       return {
 
-         width: getCSSInt(element, 'border' + side + 'Width'),
 
-         color: getCSS(element, 'border' + side + 'Color')
 
-       };
 
-     });
 
-   }
 
-   function getBorderRadiusData(element) {
 
-     return ["TopLeft", "TopRight", "BottomRight", "BottomLeft"].map(function(side) {
 
-       return getCSS(element, 'border' + side + 'Radius');
 
-     });
 
-   }
 
-   function getCurvePoints(x, y, r1, r2) {
 
-     var kappa = 4 * ((Math.sqrt(2) - 1) / 3);
 
-     var ox = (r1) * kappa, // control point offset horizontal
 
-     oy = (r2) * kappa, // control point offset vertical
 
-     xm = x + r1, // x-middle
 
-     ym = y + r2; // y-middle
 
-     return {
 
-       topLeft: bezierCurve({
 
-         x:x,
 
-         y:ym
 
-       }, {
 
-         x:x,
 
-         y:ym - oy
 
-       }, {
 
-         x:xm - ox,
 
-         y:y
 
-       }, {
 
-         x:xm,
 
-         y:y
 
-       }),
 
-       topRight: bezierCurve({
 
-         x:x,
 
-         y:y
 
-       }, {
 
-         x:x + ox,
 
-         y:y
 
-       }, {
 
-         x:xm,
 
-         y:ym - oy
 
-       }, {
 
-         x:xm,
 
-         y:ym
 
-       }),
 
-       bottomRight: bezierCurve({
 
-         x:xm,
 
-         y:y
 
-       }, {
 
-         x:xm,
 
-         y:y + oy
 
-       }, {
 
-         x:x + ox,
 
-         y:ym
 
-       }, {
 
-         x:x,
 
-         y:ym
 
-       }),
 
-       bottomLeft: bezierCurve({
 
-         x:xm,
 
-         y:ym
 
-       }, {
 
-         x:xm - ox,
 
-         y:ym
 
-       }, {
 
-         x:x,
 
-         y:y + oy
 
-       }, {
 
-         x:x,
 
-         y:y
 
-       })
 
-     };
 
-   }
 
-   function bezierCurve(start, startControl, endControl, end) {
 
-     var lerp = function (a, b, t) {
 
-       return {
 
-         x:a.x + (b.x - a.x) * t,
 
-         y:a.y + (b.y - a.y) * t
 
-       };
 
-     };
 
-     return {
 
-       start: start,
 
-       startControl: startControl,
 
-       endControl: endControl,
 
-       end: end,
 
-       subdivide: function(t) {
 
-         var ab = lerp(start, startControl, t),
 
-         bc = lerp(startControl, endControl, t),
 
-         cd = lerp(endControl, end, t),
 
-         abbc = lerp(ab, bc, t),
 
-         bccd = lerp(bc, cd, t),
 
-         dest = lerp(abbc, bccd, t);
 
-         return [bezierCurve(start, ab, abbc, dest), bezierCurve(dest, bccd, cd, end)];
 
-       },
 
-       curveTo: function(borderArgs) {
 
-         borderArgs.push(["bezierCurve", startControl.x, startControl.y, endControl.x, endControl.y, end.x, end.y]);
 
-       },
 
-       curveToReversed: function(borderArgs) {
 
-         borderArgs.push(["bezierCurve", endControl.x, endControl.y, startControl.x, startControl.y, start.x, start.y]);
 
-       }
 
-     };
 
-   }
 
-   function parseCorner(borderArgs, radius1, radius2, corner1, corner2, x, y) {
 
-     if (radius1[0] > 0 || radius1[1] > 0) {
 
-       borderArgs.push(["line", corner1[0].start.x, corner1[0].start.y]);
 
-       corner1[0].curveTo(borderArgs);
 
-       corner1[1].curveTo(borderArgs);
 
-     } else {
 
-       borderArgs.push(["line", x, y]);
 
-     }
 
-     if (radius2[0] > 0 || radius2[1] > 0) {
 
-       borderArgs.push(["line", corner2[0].start.x, corner2[0].start.y]);
 
-     }
 
-   }
 
-   function drawSide(borderData, radius1, radius2, outer1, inner1, outer2, inner2) {
 
-     var borderArgs = [];
 
-     if (radius1[0] > 0 || radius1[1] > 0) {
 
-       borderArgs.push(["line", outer1[1].start.x, outer1[1].start.y]);
 
-       outer1[1].curveTo(borderArgs);
 
-     } else {
 
-       borderArgs.push([ "line", borderData.c1[0], borderData.c1[1]]);
 
-     }
 
-     if (radius2[0] > 0 || radius2[1] > 0) {
 
-       borderArgs.push(["line", outer2[0].start.x, outer2[0].start.y]);
 
-       outer2[0].curveTo(borderArgs);
 
-       borderArgs.push(["line", inner2[0].end.x, inner2[0].end.y]);
 
-       inner2[0].curveToReversed(borderArgs);
 
-     } else {
 
-       borderArgs.push([ "line", borderData.c2[0], borderData.c2[1]]);
 
-       borderArgs.push([ "line", borderData.c3[0], borderData.c3[1]]);
 
-     }
 
-     if (radius1[0] > 0 || radius1[1] > 0) {
 
-       borderArgs.push(["line", inner1[1].end.x, inner1[1].end.y]);
 
-       inner1[1].curveToReversed(borderArgs);
 
-     } else {
 
-       borderArgs.push([ "line", borderData.c4[0], borderData.c4[1]]);
 
-     }
 
-     return borderArgs;
 
-   }
 
-   function calculateCurvePoints(bounds, borderRadius, borders) {
 
-     var x = bounds.left,
 
-     y = bounds.top,
 
-     width = bounds.width,
 
-     height = bounds.height,
 
-     tlh = borderRadius[0][0],
 
-     tlv = borderRadius[0][1],
 
-     trh = borderRadius[1][0],
 
-     trv = borderRadius[1][1],
 
-     brh = borderRadius[2][0],
 
-     brv = borderRadius[2][1],
 
-     blh = borderRadius[3][0],
 
-     blv = borderRadius[3][1],
 
-     topWidth = width - trh,
 
-     rightHeight = height - brv,
 
-     bottomWidth = width - brh,
 
-     leftHeight = height - blv;
 
-     return {
 
-       topLeftOuter: getCurvePoints(
 
-         x,
 
-         y,
 
-         tlh,
 
-         tlv
 
-         ).topLeft.subdivide(0.5),
 
-       topLeftInner: getCurvePoints(
 
-         x + borders[3].width,
 
-         y + borders[0].width,
 
-         Math.max(0, tlh - borders[3].width),
 
-         Math.max(0, tlv - borders[0].width)
 
-         ).topLeft.subdivide(0.5),
 
-       topRightOuter: getCurvePoints(
 
-         x + topWidth,
 
-         y,
 
-         trh,
 
-         trv
 
-         ).topRight.subdivide(0.5),
 
-       topRightInner: getCurvePoints(
 
-         x + Math.min(topWidth, width + borders[3].width),
 
-         y + borders[0].width,
 
-         (topWidth > width + borders[3].width) ? 0 :trh - borders[3].width,
 
-         trv - borders[0].width
 
-         ).topRight.subdivide(0.5),
 
-       bottomRightOuter: getCurvePoints(
 
-         x + bottomWidth,
 
-         y + rightHeight,
 
-         brh,
 
-         brv
 
-         ).bottomRight.subdivide(0.5),
 
-       bottomRightInner: getCurvePoints(
 
-         x + Math.min(bottomWidth, width + borders[3].width),
 
-         y + Math.min(rightHeight, height + borders[0].width),
 
-         Math.max(0, brh - borders[1].width),
 
-         Math.max(0, brv - borders[2].width)
 
-         ).bottomRight.subdivide(0.5),
 
-       bottomLeftOuter: getCurvePoints(
 
-         x,
 
-         y + leftHeight,
 
-         blh,
 
-         blv
 
-         ).bottomLeft.subdivide(0.5),
 
-       bottomLeftInner: getCurvePoints(
 
-         x + borders[3].width,
 
-         y + leftHeight,
 
-         Math.max(0, blh - borders[3].width),
 
-         Math.max(0, blv - borders[2].width)
 
-         ).bottomLeft.subdivide(0.5)
 
-     };
 
-   }
 
-   function getBorderClip(element, borderPoints, borders, radius, bounds) {
 
-     var backgroundClip = getCSS(element, 'backgroundClip'),
 
-     borderArgs = [];
 
-     switch(backgroundClip) {
 
-       case "content-box":
 
-       case "padding-box":
 
-         parseCorner(borderArgs, radius[0], radius[1], borderPoints.topLeftInner, borderPoints.topRightInner, bounds.left + borders[3].width, bounds.top + borders[0].width);
 
-         parseCorner(borderArgs, radius[1], radius[2], borderPoints.topRightInner, borderPoints.bottomRightInner, bounds.left + bounds.width - borders[1].width, bounds.top + borders[0].width);
 
-         parseCorner(borderArgs, radius[2], radius[3], borderPoints.bottomRightInner, borderPoints.bottomLeftInner, bounds.left + bounds.width - borders[1].width, bounds.top + bounds.height - borders[2].width);
 
-         parseCorner(borderArgs, radius[3], radius[0], borderPoints.bottomLeftInner, borderPoints.topLeftInner, bounds.left + borders[3].width, bounds.top + bounds.height - borders[2].width);
 
-         break;
 
-       default:
 
-         parseCorner(borderArgs, radius[0], radius[1], borderPoints.topLeftOuter, borderPoints.topRightOuter, bounds.left, bounds.top);
 
-         parseCorner(borderArgs, radius[1], radius[2], borderPoints.topRightOuter, borderPoints.bottomRightOuter, bounds.left + bounds.width, bounds.top);
 
-         parseCorner(borderArgs, radius[2], radius[3], borderPoints.bottomRightOuter, borderPoints.bottomLeftOuter, bounds.left + bounds.width, bounds.top + bounds.height);
 
-         parseCorner(borderArgs, radius[3], radius[0], borderPoints.bottomLeftOuter, borderPoints.topLeftOuter, bounds.left, bounds.top + bounds.height);
 
-         break;
 
-     }
 
-     return borderArgs;
 
-   }
 
-   function parseBorders(element, bounds, borders){
 
-     var x = bounds.left,
 
-     y = bounds.top,
 
-     width = bounds.width,
 
-     height = bounds.height,
 
-     borderSide,
 
-     bx,
 
-     by,
 
-     bw,
 
-     bh,
 
-     borderArgs,
 
-     // http://www.w3.org/TR/css3-background/#the-border-radius
 
-     borderRadius = getBorderRadiusData(element),
 
-     borderPoints = calculateCurvePoints(bounds, borderRadius, borders),
 
-     borderData = {
 
-       clip: getBorderClip(element, borderPoints, borders, borderRadius, bounds),
 
-       borders: []
 
-     };
 
-     for (borderSide = 0; borderSide < 4; borderSide++) {
 
-       if (borders[borderSide].width > 0) {
 
-         bx = x;
 
-         by = y;
 
-         bw = width;
 
-         bh = height - (borders[2].width);
 
-         switch(borderSide) {
 
-           case 0:
 
-             // top border
 
-             bh = borders[0].width;
 
-             borderArgs = drawSide({
 
-               c1: [bx, by],
 
-               c2: [bx + bw, by],
 
-               c3: [bx + bw - borders[1].width, by + bh],
 
-               c4: [bx + borders[3].width, by + bh]
 
-             }, borderRadius[0], borderRadius[1],
 
-             borderPoints.topLeftOuter, borderPoints.topLeftInner, borderPoints.topRightOuter, borderPoints.topRightInner);
 
-             break;
 
-           case 1:
 
-             // right border
 
-             bx = x + width - (borders[1].width);
 
-             bw = borders[1].width;
 
-             borderArgs = drawSide({
 
-               c1: [bx + bw, by],
 
-               c2: [bx + bw, by + bh + borders[2].width],
 
-               c3: [bx, by + bh],
 
-               c4: [bx, by + borders[0].width]
 
-             }, borderRadius[1], borderRadius[2],
 
-             borderPoints.topRightOuter, borderPoints.topRightInner, borderPoints.bottomRightOuter, borderPoints.bottomRightInner);
 
-             break;
 
-           case 2:
 
-             // bottom border
 
-             by = (by + height) - (borders[2].width);
 
-             bh = borders[2].width;
 
-             borderArgs = drawSide({
 
-               c1: [bx + bw, by + bh],
 
-               c2: [bx, by + bh],
 
-               c3: [bx + borders[3].width, by],
 
-               c4: [bx + bw - borders[3].width, by]
 
-             }, borderRadius[2], borderRadius[3],
 
-             borderPoints.bottomRightOuter, borderPoints.bottomRightInner, borderPoints.bottomLeftOuter, borderPoints.bottomLeftInner);
 
-             break;
 
-           case 3:
 
-             // left border
 
-             bw = borders[3].width;
 
-             borderArgs = drawSide({
 
-               c1: [bx, by + bh + borders[2].width],
 
-               c2: [bx, by],
 
-               c3: [bx + bw, by + borders[0].width],
 
-               c4: [bx + bw, by + bh]
 
-             }, borderRadius[3], borderRadius[0],
 
-             borderPoints.bottomLeftOuter, borderPoints.bottomLeftInner, borderPoints.topLeftOuter, borderPoints.topLeftInner);
 
-             break;
 
-         }
 
-         borderData.borders.push({
 
-           args: borderArgs,
 
-           color: borders[borderSide].color
 
-         });
 
-       }
 
-     }
 
-     return borderData;
 
-   }
 
-   function createShape(ctx, args) {
 
-     var shape = ctx.drawShape();
 
-     args.forEach(function(border, index) {
 
-       shape[(index === 0) ? "moveTo" : border[0] + "To" ].apply(null, border.slice(1));
 
-     });
 
-     return shape;
 
-   }
 
-   function renderBorders(ctx, borderArgs, color) {
 
-     if (color !== "transparent") {
 
-       ctx.setVariable( "fillStyle", color);
 
-       createShape(ctx, borderArgs);
 
-       ctx.fill();
 
-       numDraws+=1;
 
-     }
 
-   }
 
-   function renderFormValue (el, bounds, stack){
 
-     var valueWrap = doc.createElement('valuewrap'),
 
-     cssPropertyArray = ['lineHeight','textAlign','fontFamily','color','fontSize','paddingLeft','paddingTop','width','height','border','borderLeftWidth','borderTopWidth'],
 
-     textValue,
 
-     textNode;
 
-     cssPropertyArray.forEach(function(property) {
 
-       try {
 
-         valueWrap.style[property] = getCSS(el, property);
 
-       } catch(e) {
 
-         // Older IE has issues with "border"
 
-         Util.log("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";
 
-     textValue = (el.nodeName === "SELECT") ? (el.options[el.selectedIndex] || 0).text : el.value;
 
-     if(!textValue) {
 
-       textValue = el.placeholder;
 
-     }
 
-     textNode = doc.createTextNode(textValue);
 
-     valueWrap.appendChild(textNode);
 
-     body.appendChild(valueWrap);
 
-     renderText(el, textNode, stack);
 
-     body.removeChild(valueWrap);
 
-   }
 
-   function drawImage (ctx) {
 
-     ctx.drawImage.apply(ctx, Array.prototype.slice.call(arguments, 1));
 
-     numDraws+=1;
 
-   }
 
-   function getPseudoElement(el, which) {
 
-     var elStyle = window.getComputedStyle(el, which);
 
-     var parentStyle = window.getComputedStyle(el);
 
-     // If no content attribute is present, the pseudo element is hidden,
 
-     // or the parent has a content property equal to the content on the pseudo element,
 
-     // move along.
 
-     if(!elStyle || !elStyle.content || elStyle.content === "none" || elStyle.content === "-moz-alt-content" ||
 
-        elStyle.display === "none" || parentStyle.content === elStyle.content) {
 
-       return;
 
-     }
 
-     var content = elStyle.content + '';
 
-     // Strip inner quotes
 
-     if(content[0] === "'" || content[0] === "\"") {
 
-       content = content.replace(/(^['"])|(['"]$)/g, '');
 
-     }
 
-     var isImage = content.substr( 0, 3 ) === 'url',
 
-     elps = document.createElement( isImage ? 'img' : 'span' );
 
-     elps.className = pseudoHide + "-element ";
 
-     Object.keys(elStyle).filter(indexedProperty).forEach(function(prop) {
 
-       // Prevent assigning of read only CSS Rules, ex. length, parentRule
 
-       try {
 
-         elps.style[prop] = elStyle[prop];
 
-       } catch (e) {
 
-         Util.log(['Tried to assign readonly property ', prop, 'Error:', e]);
 
-       }
 
-     });
 
-     if(isImage) {
 
-       elps.src = Util.parseBackgroundImage(content)[0].args[0];
 
-     } else {
 
-       elps.innerHTML = content;
 
-     }
 
-     return elps;
 
-   }
 
-   function indexedProperty(property) {
 
-     return (isNaN(window.parseInt(property, 10)));
 
-   }
 
-   function renderBackgroundRepeat(ctx, image, backgroundPosition, bounds) {
 
-     var offsetX = Math.round(bounds.left + backgroundPosition.left),
 
-     offsetY = Math.round(bounds.top + backgroundPosition.top);
 
-     ctx.createPattern(image);
 
-     ctx.translate(offsetX, offsetY);
 
-     ctx.fill();
 
-     ctx.translate(-offsetX, -offsetY);
 
-   }
 
-   function backgroundRepeatShape(ctx, image, backgroundPosition, bounds, left, top, width, height) {
 
-     var args = [];
 
-     args.push(["line", Math.round(left), Math.round(top)]);
 
-     args.push(["line", Math.round(left + width), Math.round(top)]);
 
-     args.push(["line", Math.round(left + width), Math.round(height + top)]);
 
-     args.push(["line", Math.round(left), Math.round(height + top)]);
 
-     createShape(ctx, args);
 
-     ctx.save();
 
-     ctx.clip();
 
-     renderBackgroundRepeat(ctx, image, backgroundPosition, bounds);
 
-     ctx.restore();
 
-   }
 
-   function renderBackgroundColor(ctx, backgroundBounds, bgcolor) {
 
-     renderRect(
 
-       ctx,
 
-       backgroundBounds.left,
 
-       backgroundBounds.top,
 
-       backgroundBounds.width,
 
-       backgroundBounds.height,
 
-       bgcolor
 
-       );
 
-   }
 
-   function renderBackgroundRepeating(el, bounds, ctx, image, imageIndex) {
 
-     var backgroundSize = Util.BackgroundSize(el, bounds, image, imageIndex),
 
-     backgroundPosition = Util.BackgroundPosition(el, bounds, image, imageIndex, backgroundSize),
 
-     backgroundRepeat = Util.BackgroundRepeat(el, imageIndex);
 
-     image = resizeImage(image, backgroundSize);
 
-     switch (backgroundRepeat) {
 
-       case "repeat-x":
 
-       case "repeat no-repeat":
 
-         backgroundRepeatShape(ctx, image, backgroundPosition, bounds,
 
-           bounds.left, bounds.top + backgroundPosition.top, 99999, image.height);
 
-         break;
 
-       case "repeat-y":
 
-       case "no-repeat repeat":
 
-         backgroundRepeatShape(ctx, image, backgroundPosition, bounds,
 
-           bounds.left + backgroundPosition.left, bounds.top, image.width, 99999);
 
-         break;
 
-       case "no-repeat":
 
-         backgroundRepeatShape(ctx, image, backgroundPosition, bounds,
 
-           bounds.left + backgroundPosition.left, bounds.top + backgroundPosition.top, image.width, image.height);
 
-         break;
 
-       default:
 
-         renderBackgroundRepeat(ctx, image, backgroundPosition, {
 
-           top: bounds.top,
 
-           left: bounds.left,
 
-           width: image.width,
 
-           height: image.height
 
-         });
 
-         break;
 
-     }
 
-   }
 
-   function renderBackgroundImage(element, bounds, ctx) {
 
-     var backgroundImage = getCSS(element, "backgroundImage"),
 
-     backgroundImages = Util.parseBackgroundImage(backgroundImage),
 
-     image,
 
-     imageIndex = backgroundImages.length;
 
-     while(imageIndex--) {
 
-       backgroundImage = backgroundImages[imageIndex];
 
-       if (!backgroundImage.args || backgroundImage.args.length === 0) {
 
-         continue;
 
-       }
 
-       var key = backgroundImage.method === 'url' ?
 
-       backgroundImage.args[0] :
 
-       backgroundImage.value;
 
-       image = loadImage(key);
 
-       // TODO add support for background-origin
 
-       if (image) {
 
-         renderBackgroundRepeating(element, bounds, ctx, image, imageIndex);
 
-       } else {
 
-         Util.log("html2canvas: Error loading background:", backgroundImage);
 
-       }
 
-     }
 
-   }
 
-   function resizeImage(image, bounds) {
 
-     if(image.width === bounds.width && image.height === bounds.height) {
 
-       return image;
 
-     }
 
-     var ctx, canvas = doc.createElement('canvas');
 
-     canvas.width = bounds.width;
 
-     canvas.height = bounds.height;
 
-     ctx = canvas.getContext("2d");
 
-     drawImage(ctx, image, 0, 0, image.width, image.height, 0, 0, bounds.width, bounds.height );
 
-     return canvas;
 
-   }
 
-   function setOpacity(ctx, element, parentStack) {
 
-     return ctx.setVariable("globalAlpha", getCSS(element, "opacity") * ((parentStack) ? parentStack.opacity : 1));
 
-   }
 
-   function removePx(str) {
 
-     return str.replace("px", "");
 
-   }
 
-   function getTransform(element, parentStack) {
 
-     var transformRegExp = /(matrix)\((.+)\)/;
 
-     var transform = getCSS(element, "transform") || getCSS(element, "-webkit-transform") || getCSS(element, "-moz-transform") || getCSS(element, "-ms-transform") || getCSS(element, "-o-transform");
 
-     var transformOrigin = getCSS(element, "transform-origin") || getCSS(element, "-webkit-transform-origin") || getCSS(element, "-moz-transform-origin") || getCSS(element, "-ms-transform-origin") || getCSS(element, "-o-transform-origin") || "0px 0px";
 
-     transformOrigin = transformOrigin.split(" ").map(removePx).map(Util.asFloat);
 
-     var matrix;
 
-     if (transform && transform !== "none") {
 
-       var match = transform.match(transformRegExp);
 
-       if (match) {
 
-         switch(match[1]) {
 
-           case "matrix":
 
-             matrix = match[2].split(",").map(Util.trimText).map(Util.asFloat);
 
-             break;
 
-         }
 
-       }
 
-     }
 
-     return {
 
-       origin: transformOrigin,
 
-       matrix: matrix
 
-     };
 
-   }
 
-   function createStack(element, parentStack, bounds, transform) {
 
-     var ctx = h2cRenderContext((!parentStack) ? documentWidth() : bounds.width , (!parentStack) ? documentHeight() : bounds.height),
 
-     stack = {
 
-       ctx: ctx,
 
-       opacity: setOpacity(ctx, element, parentStack),
 
-       cssPosition: getCSS(element, "position"),
 
-       borders: getBorderData(element),
 
-       transform: transform,
 
-       clip: (parentStack && parentStack.clip) ? Util.Extend( {}, parentStack.clip ) : null
 
-     };
 
-     setZ(element, stack, parentStack);
 
-     // TODO correct overflow for absolute content residing under a static position
 
-     if (options.useOverflow === true && /(hidden|scroll|auto)/.test(getCSS(element, "overflow")) === true && /(BODY)/i.test(element.nodeName) === false){
 
-       stack.clip = (stack.clip) ? clipBounds(stack.clip, bounds) : bounds;
 
-     }
 
-     return stack;
 
-   }
 
-   function getBackgroundBounds(borders, bounds, clip) {
 
-     var backgroundBounds = {
 
-       left: bounds.left + borders[3].width,
 
-       top: bounds.top + borders[0].width,
 
-       width: bounds.width - (borders[1].width + borders[3].width),
 
-       height: bounds.height - (borders[0].width + borders[2].width)
 
-     };
 
-     if (clip) {
 
-       backgroundBounds = clipBounds(backgroundBounds, clip);
 
-     }
 
-     return backgroundBounds;
 
-   }
 
-   function getBounds(element, transform) {
 
-     var bounds = (transform.matrix) ? Util.OffsetBounds(element) : Util.Bounds(element);
 
-     transform.origin[0] += bounds.left;
 
-     transform.origin[1] += bounds.top;
 
-     return bounds;
 
-   }
 
-   function renderElement(element, parentStack, ignoreBackground) {
 
-     var transform = getTransform(element, parentStack),
 
-     bounds = getBounds(element, transform),
 
-     image,
 
-     stack = createStack(element, parentStack, bounds, transform),
 
-     borders = stack.borders,
 
-     ctx = stack.ctx,
 
-     backgroundBounds = getBackgroundBounds(borders, bounds, stack.clip),
 
-     borderData = parseBorders(element, bounds, borders),
 
-     backgroundColor = (ignoreElementsRegExp.test(element.nodeName)) ? "#efefef" : getCSS(element, "backgroundColor");
 
-     createShape(ctx, borderData.clip);
 
-     ctx.save();
 
-     ctx.clip();
 
-     if (backgroundBounds.height > 0 && backgroundBounds.width > 0 && !ignoreBackground) {
 
-       renderBackgroundColor(ctx, bounds, backgroundColor);
 
-       renderBackgroundImage(element, backgroundBounds, ctx);
 
-     } else if (ignoreBackground) {
 
-       stack.backgroundColor =  backgroundColor;
 
-     }
 
-     ctx.restore();
 
-     borderData.borders.forEach(function(border) {
 
-       renderBorders(ctx, border.args, border.color);
 
-     });
 
-     switch(element.nodeName){
 
-       case "IMG":
 
-         if ((image = loadImage(element.getAttribute('src')))) {
 
-           renderImage(ctx, element, image, bounds, borders);
 
-         } else {
 
-           Util.log("html2canvas: Error loading <img>:" + element.getAttribute('src'));
 
-         }
 
-         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(element.type) && (element.value || element.placeholder || "").length > 0){
 
-           renderFormValue(element, bounds, stack);
 
-         }
 
-         break;
 
-       case "TEXTAREA":
 
-         if ((element.value || element.placeholder || "").length > 0){
 
-           renderFormValue(element, bounds, stack);
 
-         }
 
-         break;
 
-       case "SELECT":
 
-         if ((element.options||element.placeholder || "").length > 0){
 
-           renderFormValue(element, bounds, stack);
 
-         }
 
-         break;
 
-       case "LI":
 
-         renderListItem(element, stack, backgroundBounds);
 
-         break;
 
-       case "CANVAS":
 
-         renderImage(ctx, element, element, bounds, borders);
 
-         break;
 
-     }
 
-     return stack;
 
-   }
 
-   function isElementVisible(element) {
 
-     return (getCSS(element, 'display') !== "none" && getCSS(element, 'visibility') !== "hidden" && !element.hasAttribute("data-html2canvas-ignore"));
 
-   }
 
-   function parseElement (element, stack, cb) {
 
-     if (!cb) {
 
-       cb = function(){};
 
-     }
 
-     if (isElementVisible(element)) {
 
-       stack = renderElement(element, stack, false) || stack;
 
-       if (!ignoreElementsRegExp.test(element.nodeName)) {
 
-         return parseChildren(element, stack, cb);
 
-       }
 
-     }
 
-     cb();
 
-   }
 
-   function parseChildren(element, stack, cb) {
 
-     var children = Util.Children(element);
 
-     // After all nodes have processed, finished() will call the cb.
 
-     // We add one and kick it off so this will still work when children.length === 0.
 
-     // Note that unless async is true, this will happen synchronously, just will callbacks.
 
-     var jobs = children.length + 1;
 
-     finished();
 
-     if (options.async) {
 
-       children.forEach(function(node) {
 
-         // Don't block the page from rendering
 
-         setTimeout(function(){ parseNode(node); }, 0);
 
-       });
 
-     } else {
 
-       children.forEach(parseNode);
 
-     }
 
-     function parseNode(node) {
 
-       if (node.nodeType === node.ELEMENT_NODE) {
 
-         parseElement(node, stack, finished);
 
-       } else if (node.nodeType === node.TEXT_NODE) {
 
-         renderText(element, node, stack);
 
-         finished();
 
-       } else {
 
-         finished();
 
-       }
 
-     }
 
-     function finished(el) {
 
-       if (--jobs <= 0){
 
-         Util.log("finished rendering " + children.length + " children.");
 
-         cb();
 
-       }
 
-     }
 
-   }
 
- };
 
- _html2canvas.Preload = function( options ) {
 
-   var images = {
 
-     numLoaded: 0,   // also failed are counted here
 
-     numFailed: 0,
 
-     numTotal: 0,
 
-     cleanupDone: false
 
-   },
 
-   pageOrigin,
 
-   Util = _html2canvas.Util,
 
-   methods,
 
-   i,
 
-   count = 0,
 
-   element = options.elements[0] || document.body,
 
-   doc = element.ownerDocument,
 
-   domImages = element.getElementsByTagName('img'), // Fetch images of the present 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(){
 
-     Util.log("html2canvas: start: images: " + images.numLoaded + " / " + images.numTotal + " (failed: " + images.numFailed + ")");
 
-     if (!images.firstRun && images.numLoaded >= images.numTotal){
 
-       Util.log("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 loadPseudoElement(element, type) {
 
-     var style = window.getComputedStyle(element, type),
 
-     content = style.content;
 
-     if (content.substr(0, 3) === 'url') {
 
-       methods.loadImage(_html2canvas.Util.parseBackgroundImage(content)[0].args[0]);
 
-     }
 
-     loadBackgroundImages(style.backgroundImage, element);
 
-   }
 
-   function loadPseudoElementImages(element) {
 
-     loadPseudoElement(element, ":before");
 
-     loadPseudoElement(element, ":after");
 
-   }
 
-   function loadGradientImage(backgroundImage, bounds) {
 
-     var img = _html2canvas.Generate.Gradient(backgroundImage, bounds);
 
-     if (img !== undefined){
 
-       images[backgroundImage] = {
 
-         img: img,
 
-         succeeded: true
 
-       };
 
-       images.numTotal++;
 
-       images.numLoaded++;
 
-       start();
 
-     }
 
-   }
 
-   function invalidBackgrounds(background_image) {
 
-     return (background_image && background_image.method && background_image.args && background_image.args.length > 0 );
 
-   }
 
-   function loadBackgroundImages(background_image, el) {
 
-     var bounds;
 
-     _html2canvas.Util.parseBackgroundImage(background_image).filter(invalidBackgrounds).forEach(function(background_image) {
 
-       if (background_image.method === 'url') {
 
-         methods.loadImage(background_image.args[0]);
 
-       } else if(background_image.method.match(/\-?gradient$/)) {
 
-         if(bounds === undefined) {
 
-           bounds = _html2canvas.Util.Bounds(el);
 
-         }
 
-         loadGradientImage(background_image.value, bounds);
 
-       }
 
-     });
 
-   }
 
-   function getImages (el) {
 
-     var elNodeType = false;
 
-     // Firefox fails with permission denied on pages with iframes
 
-     try {
 
-       Util.Children(el).forEach(getImages);
 
-     }
 
-     catch( e ) {}
 
-     try {
 
-       elNodeType = el.nodeType;
 
-     } catch (ex) {
 
-       elNodeType = false;
 
-       Util.log("html2canvas: failed to access some element's nodeType - Exception: " + ex.message);
 
-     }
 
-     if (elNodeType === 1 || elNodeType === undefined) {
 
-       loadPseudoElementImages(el);
 
-       try {
 
-         loadBackgroundImages(Util.getCSS(el, 'backgroundImage'), el);
 
-       } catch(e) {
 
-         Util.log("html2canvas: failed to get background-image - Exception: " + e.message);
 
-       }
 
-       loadBackgroundImages(el);
 
-     }
 
-   }
 
-   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();
 
-     };
 
-   }
 
-   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;
 
-         } 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") {
 
-           Util.log("html2canvas: Cleanup because: " + cause);
 
-         } else {
 
-           Util.log("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++;
 
-               Util.log("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);
 
-   }
 
-   Util.log('html2canvas: Preload starts: finding background-images');
 
-   images.firstRun = true;
 
-   getImages(element);
 
-   Util.log('html2canvas: Preload: Finding images');
 
-   // load <img> images
 
-   for (i = 0; i < imgLen; i+=1){
 
-     methods.loadImage( domImages[i].getAttribute( "src" ) );
 
-   }
 
-   images.firstRun = false;
 
-   Util.log('html2canvas: Preload: Done.');
 
-   if (images.numTotal === images.numLoaded) {
 
-     start();
 
-   }
 
-   return methods;
 
- };
 
- _html2canvas.Renderer = function(parseQueue, options){
 
-   function sortZindex(a, b) {
 
-     if (a === 'children') {
 
-       return -1;
 
-     } else if (b === 'children') {
 
-       return 1;
 
-     } else {
 
-       return a - b;
 
-     }
 
-   }
 
-   // http://www.w3.org/TR/CSS21/zindex.html
 
-   function createRenderQueue(parseQueue) {
 
-     var queue = [],
 
-     rootContext;
 
-     rootContext = (function buildStackingContext(rootNode) {
 
-       var rootContext = {};
 
-       function insert(context, node, specialParent) {
 
-         var zi = (node.zIndex.zindex === 'auto') ? 0 : Number(node.zIndex.zindex),
 
-         contextForChildren = context, // the stacking context for children
 
-         isPositioned = node.zIndex.isPositioned,
 
-         isFloated = node.zIndex.isFloated,
 
-         stub = {node: node},
 
-         childrenDest = specialParent; // where children without z-index should be pushed into
 
-         if (node.zIndex.ownStacking) {
 
-           contextForChildren = stub.context = {
 
-               children: [{node:node, children: []}]
 
-           };
 
-           childrenDest = undefined;
 
-         } else if (isPositioned || isFloated) {
 
-           childrenDest = stub.children = [];
 
-         }
 
-         if (zi === 0 && specialParent) {
 
-           specialParent.push(stub);
 
-         } else {
 
-           if (!context[zi]) { context[zi] = []; }
 
-           context[zi].push(stub);
 
-         }
 
-         node.zIndex.children.forEach(function(childNode) {
 
-           insert(contextForChildren, childNode, childrenDest);
 
-         });
 
-       }
 
-       insert(rootContext, rootNode);
 
-       return rootContext;
 
-     })(parseQueue);
 
-     function sortZ(context) {
 
-       Object.keys(context).sort(sortZindex).forEach(function(zi) {
 
-         var nonPositioned = [],
 
-         floated = [],
 
-         positioned = [],
 
-         list = [];
 
-         // positioned after static
 
-         context[zi].forEach(function(v) {
 
-           if (v.node.zIndex.isPositioned || v.node.zIndex.opacity < 1) {
 
-             // http://www.w3.org/TR/css3-color/#transparency
 
-             // non-positioned element with opactiy < 1 should be stacked as if it were a positioned element with ‘z-index: 0’ and ‘opacity: 1’.
 
-             positioned.push(v);
 
-           } else if (v.node.zIndex.isFloated) {
 
-             floated.push(v);
 
-           } else {
 
-             nonPositioned.push(v);
 
-           }
 
-         });
 
-         (function walk(arr) {
 
-           arr.forEach(function(v) {
 
-             list.push(v);
 
-             if (v.children) { walk(v.children); }
 
-           });
 
-         })(nonPositioned.concat(floated, positioned));
 
-         list.forEach(function(v) {
 
-           if (v.context) {
 
-             sortZ(v.context);
 
-           } else {
 
-             queue.push(v.node);
 
-           }
 
-         });
 
-       });
 
-     }
 
-     sortZ(rootContext);
 
-     return queue;
 
-   }
 
-   function getRenderer(rendererName) {
 
-     var renderer;
 
-     if (typeof options.renderer === "string" && _html2canvas.Renderer[rendererName] !== undefined) {
 
-       renderer = _html2canvas.Renderer[rendererName](options);
 
-     } else if (typeof rendererName === "function") {
 
-       renderer = rendererName(options);
 
-     } else {
 
-       throw new Error("Unknown renderer");
 
-     }
 
-     if ( typeof renderer !== "function" ) {
 
-       throw new Error("Invalid renderer defined");
 
-     }
 
-     return renderer;
 
-   }
 
-   return getRenderer(options.renderer)(parseQueue, options, document, createRenderQueue(parseQueue.stack), _html2canvas);
 
- };
 
- _html2canvas.Util.Support = function (options, doc) {
 
-   function supportSVGRendering() {
 
-     var img = new Image(),
 
-     canvas = doc.createElement("canvas"),
 
-     ctx = (canvas.getContext === undefined) ? false : canvas.getContext("2d");
 
-     if (ctx === false) {
 
-       return false;
 
-     }
 
-     canvas.width = canvas.height = 10;
 
-     img.src = [
 
-     "data:image/svg+xml,",
 
-     "<svg xmlns='http://www.w3.org/2000/svg' width='10' height='10'>",
 
-     "<foreignObject width='10' height='10'>",
 
-     "<div xmlns='http://www.w3.org/1999/xhtml' style='width:10;height:10;'>",
 
-     "sup",
 
-     "</div>",
 
-     "</foreignObject>",
 
-     "</svg>"
 
-     ].join("");
 
-     try {
 
-       ctx.drawImage(img, 0, 0);
 
-       canvas.toDataURL();
 
-     } catch(e) {
 
-       return false;
 
-     }
 
-     _html2canvas.Util.log('html2canvas: Parse: SVG powered rendering available');
 
-     return true;
 
-   }
 
-   // Test whether we can use ranges to measure bounding boxes
 
-   // Opera doesn't provide valid bounds.height/bottom even though it supports the method.
 
-   function supportRangeBounds() {
 
-     var r, testElement, rangeBounds, rangeHeight, support = false;
 
-     if (doc.createRange) {
 
-       r = doc.createRange();
 
-       if (r.getBoundingClientRect) {
 
-         testElement = doc.createElement('boundtest');
 
-         testElement.style.height = "123px";
 
-         testElement.style.display = "block";
 
-         doc.body.appendChild(testElement);
 
-         r.selectNode(testElement);
 
-         rangeBounds = r.getBoundingClientRect();
 
-         rangeHeight = rangeBounds.height;
 
-         if (rangeHeight === 123) {
 
-           support = true;
 
-         }
 
-         doc.body.removeChild(testElement);
 
-       }
 
-     }
 
-     return support;
 
-   }
 
-   return {
 
-     rangeBounds: supportRangeBounds(),
 
-     svgRendering: options.svgRendering && supportSVGRendering()
 
-   };
 
- };
 
- window.html2canvas = function(elements, opts) {
 
-   elements = (elements.length) ? elements : [elements];
 
-   var queue,
 
-   canvas,
 
-   options = {
 
-     // general
 
-     logging: false,
 
-     elements: elements,
 
-     background: "#fff",
 
-     // preload options
 
-     proxy: null,
 
-     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+)
 
-     ignoreElements: "IFRAME|OBJECT|PARAM",
 
-     useOverflow: true,
 
-     letterRendering: false,
 
-     chinese: false,
 
-     async: false, // If true, parsing will not block, but if the user scrolls during parse the image can get weird
 
-     // render options
 
-     width: null,
 
-     height: null,
 
-     taintTest: true, // do a taint test with all images before applying to canvas
 
-     renderer: "Canvas"
 
-   };
 
-   options = _html2canvas.Util.Extend(opts, options);
 
-   _html2canvas.logging = options.logging;
 
-   options.complete = function( images ) {
 
-     if (typeof options.onpreloaded === "function") {
 
-       if ( options.onpreloaded( images ) === false ) {
 
-         return;
 
-       }
 
-     }
 
-     _html2canvas.Parse( images, options, function(queue) {
 
-       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: _html2canvas.Util.log
 
-   };
 
- };
 
- window.html2canvas.log = _html2canvas.Util.log; // for renderers
 
- window.html2canvas.Renderer = {
 
-   Canvas: undefined // We are assuming this will be used
 
- };
 
- _html2canvas.Renderer.Canvas = function(options) {
 
-   options = options || {};
 
-   var doc = document,
 
-   safeImages = [],
 
-   testCanvas = document.createElement("canvas"),
 
-   testctx = testCanvas.getContext("2d"),
 
-   Util = _html2canvas.Util,
 
-   canvas = options.canvas || doc.createElement('canvas');
 
-   function createShape(ctx, args) {
 
-     ctx.beginPath();
 
-     args.forEach(function(arg) {
 
-       ctx[arg.name].apply(ctx, arg['arguments']);
 
-     });
 
-     ctx.closePath();
 
-   }
 
-   function safeImage(item) {
 
-     if (safeImages.indexOf(item['arguments'][0].src) === -1) {
 
-       testctx.drawImage(item['arguments'][0], 0, 0);
 
-       try {
 
-         testctx.getImageData(0, 0, 1, 1);
 
-       } catch(e) {
 
-         testCanvas = doc.createElement("canvas");
 
-         testctx = testCanvas.getContext("2d");
 
-         return false;
 
-       }
 
-       safeImages.push(item['arguments'][0].src);
 
-     }
 
-     return true;
 
-   }
 
-   function renderItem(ctx, item) {
 
-     switch(item.type){
 
-       case "variable":
 
-         ctx[item.name] = item['arguments'];
 
-         break;
 
-       case "function":
 
-         switch(item.name) {
 
-           case "createPattern":
 
-             if (item['arguments'][0].width > 0 && item['arguments'][0].height > 0) {
 
-               try {
 
-                 ctx.fillStyle = ctx.createPattern(item['arguments'][0], "repeat");
 
-               } catch(e) {
 
-                 Util.log("html2canvas: Renderer: Error creating pattern", e.message);
 
-               }
 
-             }
 
-             break;
 
-           case "drawShape":
 
-             createShape(ctx, item['arguments']);
 
-             break;
 
-           case "drawImage":
 
-             if (item['arguments'][8] > 0 && item['arguments'][7] > 0) {
 
-               if (!options.taintTest || (options.taintTest && safeImage(item))) {
 
-                 ctx.drawImage.apply( ctx, item['arguments'] );
 
-               }
 
-             }
 
-             break;
 
-           default:
 
-             ctx[item.name].apply(ctx, item['arguments']);
 
-         }
 
-         break;
 
-     }
 
-   }
 
-   return function(parsedData, options, document, queue, _html2canvas) {
 
-     var ctx = canvas.getContext("2d"),
 
-     newCanvas,
 
-     bounds,
 
-     fstyle,
 
-     zStack = parsedData.stack;
 
-     canvas.width = canvas.style.width =  options.width || zStack.ctx.width;
 
-     canvas.height = canvas.style.height = options.height || zStack.ctx.height;
 
-     fstyle = ctx.fillStyle;
 
-     ctx.fillStyle = (Util.isTransparent(parsedData.backgroundColor) && options.background !== undefined) ? options.background : parsedData.backgroundColor;
 
-     ctx.fillRect(0, 0, canvas.width, canvas.height);
 
-     ctx.fillStyle = fstyle;
 
-     queue.forEach(function(storageContext) {
 
-       // set common settings for canvas
 
-       ctx.textBaseline = "bottom";
 
-       ctx.save();
 
-       if (storageContext.transform.matrix) {
 
-         ctx.translate(storageContext.transform.origin[0], storageContext.transform.origin[1]);
 
-         ctx.transform.apply(ctx, storageContext.transform.matrix);
 
-         ctx.translate(-storageContext.transform.origin[0], -storageContext.transform.origin[1]);
 
-       }
 
-       if (storageContext.clip){
 
-         ctx.beginPath();
 
-         ctx.rect(storageContext.clip.left, storageContext.clip.top, storageContext.clip.width, storageContext.clip.height);
 
-         ctx.clip();
 
-       }
 
-       if (storageContext.ctx.storage) {
 
-         storageContext.ctx.storage.forEach(function(item) {
 
-           renderItem(ctx, item);
 
-         });
 
-       }
 
-       ctx.restore();
 
-     });
 
-     Util.log("html2canvas: Renderer: Canvas renderer done - returning canvas obj");
 
-     if (options.elements.length === 1) {
 
-       if (typeof options.elements[0] === "object" && options.elements[0].nodeName !== "BODY") {
 
-         // crop image to the bounds of selected (single) element
 
-         bounds = _html2canvas.Util.Bounds(options.elements[0]);
 
-         newCanvas = document.createElement('canvas');
 
-         
 
- 	    newCanvas.width = Math.ceil(bounds.width);
 
-         newCanvas.height = Math.ceil(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;
 
-       }
 
-     }
 
-     return canvas;
 
-   };
 
- };
 
- })(window,document);
 
 
  |