corrade-nucleus-nucleons

Subversion Repositories:
Compare Path: Rev
With Path: Rev
?path1? @ 19  →  ?path2? @ 20
/base/000_base/node_modules/highcharts/lib/canvg.js
@@ -0,0 +1,130 @@
/*
 
canvg.js - Javascript SVG parser and renderer on Canvas
MIT Licensed
Gabe Lerner (gabelerner@gmail.com)
http://code.google.com/p/canvg/
 
Requires: rgbcolor.js - http://www.phpied.com/rgb-color-parser-in-javascript/
*/
(function(x,y){"undefined"!==typeof define&&define.amd?define("canvgModule",["rgbcolor","stackblur"],y):"undefined"!==typeof module&&module.exports&&(module.exports=y(require("rgbcolor"),require("stackblur")));x.canvg=y(x.RGBColor,x.stackBlur)})("undefined"!==typeof window?window:this,function(x,y){function A(h){var a=[0,0,0],l=function(c,b){var e=h.match(c);null!=e&&(a[b]+=e.length,h=h.replace(c," "))};h=h.replace(/:not\(([^\)]*)\)/g," $1 ");h=h.replace(/{[^]*/gm," ");l(B,1);l(C,0);l(D,1);l(E,
2);l(F,1);l(G,1);h=h.replace(/[\*\s\+>~]/g," ");h=h.replace(/[#\.]/g," ");l(H,2);return a.join("")}function I(h){var a={opts:h,FRAMERATE:30,MAX_VIRTUAL_PIXELS:3E4,log:function(a){}};1==a.opts.log&&"undefined"!=typeof console&&(a.log=function(a){console.log(a)});a.init=function(c){var b=0;a.UniqueId=function(){b++;return"canvg"+b};a.Definitions={};a.Styles={};a.StylesSpecificity={};a.Animations=[];a.Images=[];a.ctx=c;a.ViewPort=new function(){this.viewPorts=[];this.Clear=function(){this.viewPorts=
[]};this.SetCurrent=function(a,b){this.viewPorts.push({width:a,height:b})};this.RemoveCurrent=function(){this.viewPorts.pop()};this.Current=function(){return this.viewPorts[this.viewPorts.length-1]};this.width=function(){return this.Current().width};this.height=function(){return this.Current().height};this.ComputeSize=function(a){return null!=a&&"number"==typeof a?a:"x"==a?this.width():"y"==a?this.height():Math.sqrt(Math.pow(this.width(),2)+Math.pow(this.height(),2))/Math.sqrt(2)}}};a.init();a.ImagesLoaded=
function(){for(var c=0;c<a.Images.length;c++)if(!a.Images[c].loaded)return!1;return!0};a.trim=function(a){return a.replace(/^\s+|\s+$/g,"")};a.compressSpaces=function(a){return a.replace(/[\s\r\t\n]+/gm," ")};a.ajax=function(a){var b;b=window.XMLHttpRequest?new XMLHttpRequest:new ActiveXObject("Microsoft.XMLHTTP");b.open("GET",a,!1);b.send(null);return b.responseText};a.parseXml=function(a){if("undefined"!=typeof Windows&&"undefined"!=typeof Windows.Data&&"undefined"!=typeof Windows.Data.Xml){var b=
new Windows.Data.Xml.Dom.XmlDocument,e=new Windows.Data.Xml.Dom.XmlLoadSettings;e.prohibitDtd=!1;b.loadXml(a,e);return b}if(window.DOMParser)return(new DOMParser).parseFromString(a,"text/xml");a=a.replace(/<!DOCTYPE svg[^>]*>/,"");b=new ActiveXObject("Microsoft.XMLDOM");b.async="false";b.loadXML(a);return b};a.Property=function(a,b){this.name=a;this.value=b};a.Property.prototype.getValue=function(){return this.value};a.Property.prototype.hasValue=function(){return null!=this.value&&""!==this.value};
a.Property.prototype.numValue=function(){if(!this.hasValue())return 0;var a=parseFloat(this.value);(this.value+"").match(/%$/)&&(a/=100);return a};a.Property.prototype.valueOrDefault=function(a){return this.hasValue()?this.value:a};a.Property.prototype.numValueOrDefault=function(a){return this.hasValue()?this.numValue():a};a.Property.prototype.addOpacity=function(c){var b=this.value;if(null!=c.value&&""!=c.value&&"string"==typeof this.value){var e=new x(this.value);e.ok&&(b="rgba("+e.r+", "+e.g+", "+
e.b+", "+c.numValue()+")")}return new a.Property(this.name,b)};a.Property.prototype.getDefinition=function(){var c=this.value.match(/#([^\)'"]+)/);c&&(c=c[1]);c||(c=this.value);return a.Definitions[c]};a.Property.prototype.isUrlDefinition=function(){return 0==this.value.indexOf("url(")};a.Property.prototype.getFillStyleDefinition=function(c,b){var e=this.getDefinition();if(null!=e&&e.createGradient)return e.createGradient(a.ctx,c,b);if(null!=e&&e.createPattern){if(e.getHrefAttribute().hasValue()){var d=
e.attribute("patternTransform"),e=e.getHrefAttribute().getDefinition();d.hasValue()&&(e.attribute("patternTransform",!0).value=d.value)}return e.createPattern(a.ctx,c)}return null};a.Property.prototype.getDPI=function(a){return 96};a.Property.prototype.getEM=function(c){var b=12,e=new a.Property("fontSize",a.Font.Parse(a.ctx.font).fontSize);e.hasValue()&&(b=e.toPixels(c));return b};a.Property.prototype.getUnits=function(){return(this.value+"").replace(/[0-9\.\-]/g,"")};a.Property.prototype.toPixels=
function(c,b){if(!this.hasValue())return 0;var e=this.value+"";if(e.match(/em$/))return this.numValue()*this.getEM(c);if(e.match(/ex$/))return this.numValue()*this.getEM(c)/2;if(e.match(/px$/))return this.numValue();if(e.match(/pt$/))return this.numValue()*this.getDPI(c)*(1/72);if(e.match(/pc$/))return 15*this.numValue();if(e.match(/cm$/))return this.numValue()*this.getDPI(c)/2.54;if(e.match(/mm$/))return this.numValue()*this.getDPI(c)/25.4;if(e.match(/in$/))return this.numValue()*this.getDPI(c);
if(e.match(/%$/))return this.numValue()*a.ViewPort.ComputeSize(c);e=this.numValue();return b&&1>e?e*a.ViewPort.ComputeSize(c):e};a.Property.prototype.toMilliseconds=function(){if(!this.hasValue())return 0;var a=this.value+"";if(a.match(/s$/))return 1E3*this.numValue();a.match(/ms$/);return this.numValue()};a.Property.prototype.toRadians=function(){if(!this.hasValue())return 0;var a=this.value+"";return a.match(/deg$/)?this.numValue()*(Math.PI/180):a.match(/grad$/)?this.numValue()*(Math.PI/200):a.match(/rad$/)?
this.numValue():this.numValue()*(Math.PI/180)};var l={baseline:"alphabetic","before-edge":"top","text-before-edge":"top",middle:"middle",central:"middle","after-edge":"bottom","text-after-edge":"bottom",ideographic:"ideographic",alphabetic:"alphabetic",hanging:"hanging",mathematical:"alphabetic"};a.Property.prototype.toTextBaseline=function(){return this.hasValue()?l[this.value]:null};a.Font=new function(){this.Styles="normal|italic|oblique|inherit";this.Variants="normal|small-caps|inherit";this.Weights=
"normal|bold|bolder|lighter|100|200|300|400|500|600|700|800|900|inherit";this.CreateFont=function(b,e,d,c,f,g){g=null!=g?this.Parse(g):this.CreateFont("","","","","",a.ctx.font);return{fontFamily:f||g.fontFamily,fontSize:c||g.fontSize,fontStyle:b||g.fontStyle,fontWeight:d||g.fontWeight,fontVariant:e||g.fontVariant,toString:function(){return[this.fontStyle,this.fontVariant,this.fontWeight,this.fontSize,this.fontFamily].join(" ")}}};var c=this;this.Parse=function(b){var e={};b=a.trim(a.compressSpaces(b||
"")).split(" ");for(var d=!1,k=!1,f=!1,g=!1,m="",n=0;n<b.length;n++)k||-1==c.Styles.indexOf(b[n])?g||-1==c.Variants.indexOf(b[n])?f||-1==c.Weights.indexOf(b[n])?d?"inherit"!=b[n]&&(m+=b[n]):("inherit"!=b[n]&&(e.fontSize=b[n].split("/")[0]),k=g=f=d=!0):("inherit"!=b[n]&&(e.fontWeight=b[n]),k=g=f=!0):("inherit"!=b[n]&&(e.fontVariant=b[n]),k=g=!0):("inherit"!=b[n]&&(e.fontStyle=b[n]),k=!0);""!=m&&(e.fontFamily=m);return e}};a.ToNumberArray=function(c){c=a.trim(a.compressSpaces((c||"").replace(/,/g," "))).split(" ");
for(var b=0;b<c.length;b++)c[b]=parseFloat(c[b]);return c};a.Point=function(a,b){this.x=a;this.y=b};a.Point.prototype.angleTo=function(a){return Math.atan2(a.y-this.y,a.x-this.x)};a.Point.prototype.applyTransform=function(a){var b=this.x*a[1]+this.y*a[3]+a[5];this.x=this.x*a[0]+this.y*a[2]+a[4];this.y=b};a.CreatePoint=function(c){c=a.ToNumberArray(c);return new a.Point(c[0],c[1])};a.CreatePath=function(c){c=a.ToNumberArray(c);for(var b=[],e=0;e<c.length;e+=2)b.push(new a.Point(c[e],c[e+1]));return b};
a.BoundingBox=function(a,b,e,d){this.y2=this.x2=this.y1=this.x1=Number.NaN;this.x=function(){return this.x1};this.y=function(){return this.y1};this.width=function(){return this.x2-this.x1};this.height=function(){return this.y2-this.y1};this.addPoint=function(a,b){if(null!=a){if(isNaN(this.x1)||isNaN(this.x2))this.x2=this.x1=a;a<this.x1&&(this.x1=a);a>this.x2&&(this.x2=a)}if(null!=b){if(isNaN(this.y1)||isNaN(this.y2))this.y2=this.y1=b;b<this.y1&&(this.y1=b);b>this.y2&&(this.y2=b)}};this.addX=function(a){this.addPoint(a,
null)};this.addY=function(a){this.addPoint(null,a)};this.addBoundingBox=function(a){this.addPoint(a.x1,a.y1);this.addPoint(a.x2,a.y2)};this.addQuadraticCurve=function(a,b,e,d,c,r){e=a+2/3*(e-a);d=b+2/3*(d-b);this.addBezierCurve(a,b,e,e+1/3*(c-a),d,d+1/3*(r-b),c,r)};this.addBezierCurve=function(a,b,e,d,c,r,u,p){var t=[a,b],h=[e,d],q=[c,r],l=[u,p];this.addPoint(t[0],t[1]);this.addPoint(l[0],l[1]);for(i=0;1>=i;i++)a=function(a){return Math.pow(1-a,3)*t[i]+3*Math.pow(1-a,2)*a*h[i]+3*(1-a)*Math.pow(a,
2)*q[i]+Math.pow(a,3)*l[i]},b=6*t[i]-12*h[i]+6*q[i],e=-3*t[i]+9*h[i]-9*q[i]+3*l[i],d=3*h[i]-3*t[i],0==e?0!=b&&(b=-d/b,0<b&&1>b&&(0==i&&this.addX(a(b)),1==i&&this.addY(a(b)))):(d=Math.pow(b,2)-4*d*e,0>d||(c=(-b+Math.sqrt(d))/(2*e),0<c&&1>c&&(0==i&&this.addX(a(c)),1==i&&this.addY(a(c))),b=(-b-Math.sqrt(d))/(2*e),0<b&&1>b&&(0==i&&this.addX(a(b)),1==i&&this.addY(a(b)))))};this.isPointInBox=function(a,b){return this.x1<=a&&a<=this.x2&&this.y1<=b&&b<=this.y2};this.addPoint(a,b);this.addPoint(e,d)};a.Transform=
function(c){var b=this;this.Type={};this.Type.translate=function(b){this.p=a.CreatePoint(b);this.apply=function(a){a.translate(this.p.x||0,this.p.y||0)};this.unapply=function(a){a.translate(-1*this.p.x||0,-1*this.p.y||0)};this.applyToPoint=function(a){a.applyTransform([1,0,0,1,this.p.x||0,this.p.y||0])}};this.Type.rotate=function(b){b=a.ToNumberArray(b);this.angle=new a.Property("angle",b[0]);this.cx=b[1]||0;this.cy=b[2]||0;this.apply=function(a){a.translate(this.cx,this.cy);a.rotate(this.angle.toRadians());
a.translate(-this.cx,-this.cy)};this.unapply=function(a){a.translate(this.cx,this.cy);a.rotate(-1*this.angle.toRadians());a.translate(-this.cx,-this.cy)};this.applyToPoint=function(a){var b=this.angle.toRadians();a.applyTransform([1,0,0,1,this.p.x||0,this.p.y||0]);a.applyTransform([Math.cos(b),Math.sin(b),-Math.sin(b),Math.cos(b),0,0]);a.applyTransform([1,0,0,1,-this.p.x||0,-this.p.y||0])}};this.Type.scale=function(b){this.p=a.CreatePoint(b);this.apply=function(a){a.scale(this.p.x||1,this.p.y||this.p.x||
1)};this.unapply=function(a){a.scale(1/this.p.x||1,1/this.p.y||this.p.x||1)};this.applyToPoint=function(a){a.applyTransform([this.p.x||0,0,0,this.p.y||0,0,0])}};this.Type.matrix=function(b){this.m=a.ToNumberArray(b);this.apply=function(a){a.transform(this.m[0],this.m[1],this.m[2],this.m[3],this.m[4],this.m[5])};this.unapply=function(a){var b=this.m[0],e=this.m[2],d=this.m[4],c=this.m[1],f=this.m[3],k=this.m[5],h=1/(b*(1*f-0*k)-e*(1*c-0*k)+d*(0*c-0*f));a.transform(h*(1*f-0*k),h*(0*k-1*c),h*(0*d-1*
e),h*(1*b-0*d),h*(e*k-d*f),h*(d*c-b*k))};this.applyToPoint=function(a){a.applyTransform(this.m)}};this.Type.SkewBase=function(e){this.base=b.Type.matrix;this.base(e);this.angle=new a.Property("angle",e)};this.Type.SkewBase.prototype=new this.Type.matrix;this.Type.skewX=function(a){this.base=b.Type.SkewBase;this.base(a);this.m=[1,0,Math.tan(this.angle.toRadians()),1,0,0]};this.Type.skewX.prototype=new this.Type.SkewBase;this.Type.skewY=function(a){this.base=b.Type.SkewBase;this.base(a);this.m=[1,Math.tan(this.angle.toRadians()),
0,1,0,0]};this.Type.skewY.prototype=new this.Type.SkewBase;this.transforms=[];this.apply=function(a){for(var b=0;b<this.transforms.length;b++)this.transforms[b].apply(a)};this.unapply=function(a){for(var b=this.transforms.length-1;0<=b;b--)this.transforms[b].unapply(a)};this.applyToPoint=function(a){for(var b=0;b<this.transforms.length;b++)this.transforms[b].applyToPoint(a)};c=a.trim(a.compressSpaces(c)).replace(/\)([a-zA-Z])/g,") $1").replace(/\)(\s?,\s?)/g,") ").split(/\s(?=[a-z])/);for(var e=0;e<
c.length;e++){var d=a.trim(c[e].split("(")[0]),k=c[e].split("(")[1].replace(")",""),k=new this.Type[d](k);k.type=d;this.transforms.push(k)}};a.AspectRatio=function(c,b,e,d,k,f,g,m,n,r){b=a.compressSpaces(b);b=b.replace(/^defer\s/,"");var h=b.split(" ")[0]||"xMidYMid";b=b.split(" ")[1]||"meet";var p=e/d,t=k/f,l=Math.min(p,t),q=Math.max(p,t);"meet"==b&&(d*=l,f*=l);"slice"==b&&(d*=q,f*=q);n=new a.Property("refX",n);r=new a.Property("refY",r);n.hasValue()&&r.hasValue()?c.translate(-l*n.toPixels("x"),
-l*r.toPixels("y")):(h.match(/^xMid/)&&("meet"==b&&l==t||"slice"==b&&q==t)&&c.translate(e/2-d/2,0),h.match(/YMid$/)&&("meet"==b&&l==p||"slice"==b&&q==p)&&c.translate(0,k/2-f/2),h.match(/^xMax/)&&("meet"==b&&l==t||"slice"==b&&q==t)&&c.translate(e-d,0),h.match(/YMax$/)&&("meet"==b&&l==p||"slice"==b&&q==p)&&c.translate(0,k-f));"none"==h?c.scale(p,t):"meet"==b?c.scale(l,l):"slice"==b&&c.scale(q,q);c.translate(null==g?0:-g,null==m?0:-m)};a.Element={};a.EmptyProperty=new a.Property("EMPTY","");a.Element.ElementBase=
function(c){this.attributes={};this.styles={};this.stylesSpecificity={};this.children=[];this.attribute=function(b,e){var d=this.attributes[b];if(null!=d)return d;1==e&&(d=new a.Property(b,""),this.attributes[b]=d);return d||a.EmptyProperty};this.getHrefAttribute=function(){for(var b in this.attributes)if("href"==b||b.match(/:href$/))return this.attributes[b];return a.EmptyProperty};this.style=function(b,e,d){var c=this.styles[b];if(null!=c)return c;var k=this.attribute(b);if(null!=k&&k.hasValue())return this.styles[b]=
k;if(1!=d&&(d=this.parent,null!=d&&(d=d.style(b),null!=d&&d.hasValue())))return d;1==e&&(c=new a.Property(b,""),this.styles[b]=c);return c||a.EmptyProperty};this.render=function(a){if("none"!=this.style("display").value&&"hidden"!=this.style("visibility").value){a.save();if(this.style("mask").hasValue()){var b=this.style("mask").getDefinition();null!=b&&b.apply(a,this)}else this.style("filter").hasValue()?(b=this.style("filter").getDefinition(),null!=b&&b.apply(a,this)):(this.setContext(a),this.renderChildren(a),
this.clearContext(a));a.restore()}};this.setContext=function(a){};this.clearContext=function(a){};this.renderChildren=function(a){for(var b=0;b<this.children.length;b++)this.children[b].render(a)};this.addChild=function(b,e){var d=b;e&&(d=a.CreateElement(b));d.parent=this;"title"!=d.type&&this.children.push(d)};this.addStylesFromStyleDefinition=function(){for(var b in a.Styles)if("@"!=b[0]&&w(c,b)){var e=a.Styles[b],d=a.StylesSpecificity[b];if(null!=e)for(var k in e){var r=this.stylesSpecificity[k];
"undefined"==typeof r&&(r="000");d>r&&(this.styles[k]=e[k],this.stylesSpecificity[k]=d)}}};if(null!=c&&1==c.nodeType){for(var b=0;b<c.attributes.length;b++){var e=c.attributes[b];this.attributes[e.nodeName]=new a.Property(e.nodeName,e.value)}this.addStylesFromStyleDefinition();if(this.attribute("style").hasValue())for(e=this.attribute("style").value.split(";"),b=0;b<e.length;b++)if(""!=a.trim(e[b])){var d=e[b].split(":"),k=a.trim(d[0]),d=a.trim(d[1]);this.styles[k]=new a.Property(k,d)}this.attribute("id").hasValue()&&
null==a.Definitions[this.attribute("id").value]&&(a.Definitions[this.attribute("id").value]=this);for(b=0;b<c.childNodes.length;b++)e=c.childNodes[b],1==e.nodeType&&this.addChild(e,!0),!this.captureTextNodes||3!=e.nodeType&&4!=e.nodeType||""!=a.compressSpaces(e.value||e.text||e.textContent||"")&&this.addChild(new a.Element.tspan(e),!1)}};a.Element.RenderedElementBase=function(c){this.base=a.Element.ElementBase;this.base(c);this.setContext=function(b){if(this.style("fill").isUrlDefinition()){var e=
this.style("fill").getFillStyleDefinition(this,this.style("fill-opacity"));null!=e&&(b.fillStyle=e)}else this.style("fill").hasValue()&&(e=this.style("fill"),"currentColor"==e.value&&(e.value=this.style("color").value),"inherit"!=e.value&&(b.fillStyle="none"==e.value?"rgba(0,0,0,0)":e.value));this.style("fill-opacity").hasValue()&&(e=new a.Property("fill",b.fillStyle),e=e.addOpacity(this.style("fill-opacity")),b.fillStyle=e.value);this.style("stroke").isUrlDefinition()?(e=this.style("stroke").getFillStyleDefinition(this,
this.style("stroke-opacity")),null!=e&&(b.strokeStyle=e)):this.style("stroke").hasValue()&&(e=this.style("stroke"),"currentColor"==e.value&&(e.value=this.style("color").value),"inherit"!=e.value&&(b.strokeStyle="none"==e.value?"rgba(0,0,0,0)":e.value));this.style("stroke-opacity").hasValue()&&(e=new a.Property("stroke",b.strokeStyle),e=e.addOpacity(this.style("stroke-opacity")),b.strokeStyle=e.value);this.style("stroke-width").hasValue()&&(e=this.style("stroke-width").toPixels(),b.lineWidth=0==e?
.001:e);this.style("stroke-linecap").hasValue()&&(b.lineCap=this.style("stroke-linecap").value);this.style("stroke-linejoin").hasValue()&&(b.lineJoin=this.style("stroke-linejoin").value);this.style("stroke-miterlimit").hasValue()&&(b.miterLimit=this.style("stroke-miterlimit").value);this.style("stroke-dasharray").hasValue()&&"none"!=this.style("stroke-dasharray").value&&(e=a.ToNumberArray(this.style("stroke-dasharray").value),"undefined"!=typeof b.setLineDash?b.setLineDash(e):"undefined"!=typeof b.webkitLineDash?
b.webkitLineDash=e:"undefined"==typeof b.mozDash||1==e.length&&0==e[0]||(b.mozDash=e),e=this.style("stroke-dashoffset").numValueOrDefault(1),"undefined"!=typeof b.lineDashOffset?b.lineDashOffset=e:"undefined"!=typeof b.webkitLineDashOffset?b.webkitLineDashOffset=e:"undefined"!=typeof b.mozDashOffset&&(b.mozDashOffset=e));"undefined"!=typeof b.font&&(b.font=a.Font.CreateFont(this.style("font-style").value,this.style("font-variant").value,this.style("font-weight").value,this.style("font-size").hasValue()?
this.style("font-size").toPixels()+"px":"",this.style("font-family").value).toString());this.style("transform",!1,!0).hasValue()&&(new a.Transform(this.style("transform",!1,!0).value)).apply(b);this.style("clip-path",!1,!0).hasValue()&&(e=this.style("clip-path",!1,!0).getDefinition(),null!=e&&e.apply(b));this.style("opacity").hasValue()&&(b.globalAlpha=this.style("opacity").numValue())}};a.Element.RenderedElementBase.prototype=new a.Element.ElementBase;a.Element.PathElementBase=function(c){this.base=
a.Element.RenderedElementBase;this.base(c);this.path=function(b){null!=b&&b.beginPath();return new a.BoundingBox};this.renderChildren=function(b){this.path(b);a.Mouse.checkPath(this,b);""!=b.fillStyle&&("inherit"!=this.style("fill-rule").valueOrDefault("inherit")?b.fill(this.style("fill-rule").value):b.fill());""!=b.strokeStyle&&b.stroke();var e=this.getMarkers();if(null!=e){if(this.style("marker-start").isUrlDefinition()){var d=this.style("marker-start").getDefinition();d.render(b,e[0][0],e[0][1])}if(this.style("marker-mid").isUrlDefinition())for(var d=
this.style("marker-mid").getDefinition(),c=1;c<e.length-1;c++)d.render(b,e[c][0],e[c][1]);this.style("marker-end").isUrlDefinition()&&(d=this.style("marker-end").getDefinition(),d.render(b,e[e.length-1][0],e[e.length-1][1]))}};this.getBoundingBox=function(){return this.path()};this.getMarkers=function(){return null}};a.Element.PathElementBase.prototype=new a.Element.RenderedElementBase;a.Element.svg=function(c){this.base=a.Element.RenderedElementBase;this.base(c);this.baseClearContext=this.clearContext;
this.clearContext=function(b){this.baseClearContext(b);a.ViewPort.RemoveCurrent()};this.baseSetContext=this.setContext;this.setContext=function(b){b.strokeStyle="rgba(0,0,0,0)";b.lineCap="butt";b.lineJoin="miter";b.miterLimit=4;"undefined"!=typeof b.font&&"undefined"!=typeof window.getComputedStyle&&(b.font=window.getComputedStyle(b.canvas).getPropertyValue("font"));this.baseSetContext(b);this.attribute("x").hasValue()||(this.attribute("x",!0).value=0);this.attribute("y").hasValue()||(this.attribute("y",
!0).value=0);b.translate(this.attribute("x").toPixels("x"),this.attribute("y").toPixels("y"));var e=a.ViewPort.width(),d=a.ViewPort.height();this.attribute("width").hasValue()||(this.attribute("width",!0).value="100%");this.attribute("height").hasValue()||(this.attribute("height",!0).value="100%");if("undefined"==typeof this.root){var e=this.attribute("width").toPixels("x"),d=this.attribute("height").toPixels("y"),c=0,f=0;this.attribute("refX").hasValue()&&this.attribute("refY").hasValue()&&(c=-this.attribute("refX").toPixels("x"),
f=-this.attribute("refY").toPixels("y"));"visible"!=this.attribute("overflow").valueOrDefault("hidden")&&(b.beginPath(),b.moveTo(c,f),b.lineTo(e,f),b.lineTo(e,d),b.lineTo(c,d),b.closePath(),b.clip())}a.ViewPort.SetCurrent(e,d);if(this.attribute("viewBox").hasValue()){var c=a.ToNumberArray(this.attribute("viewBox").value),f=c[0],g=c[1],e=c[2],d=c[3];a.AspectRatio(b,this.attribute("preserveAspectRatio").value,a.ViewPort.width(),e,a.ViewPort.height(),d,f,g,this.attribute("refX").value,this.attribute("refY").value);
a.ViewPort.RemoveCurrent();a.ViewPort.SetCurrent(c[2],c[3])}}};a.Element.svg.prototype=new a.Element.RenderedElementBase;a.Element.rect=function(c){this.base=a.Element.PathElementBase;this.base(c);this.path=function(b){var e=this.attribute("x").toPixels("x"),d=this.attribute("y").toPixels("y"),c=this.attribute("width").toPixels("x"),f=this.attribute("height").toPixels("y"),g=this.attribute("rx").toPixels("x"),m=this.attribute("ry").toPixels("y");this.attribute("rx").hasValue()&&!this.attribute("ry").hasValue()&&
(m=g);this.attribute("ry").hasValue()&&!this.attribute("rx").hasValue()&&(g=m);g=Math.min(g,c/2);m=Math.min(m,f/2);null!=b&&(b.beginPath(),b.moveTo(e+g,d),b.lineTo(e+c-g,d),b.quadraticCurveTo(e+c,d,e+c,d+m),b.lineTo(e+c,d+f-m),b.quadraticCurveTo(e+c,d+f,e+c-g,d+f),b.lineTo(e+g,d+f),b.quadraticCurveTo(e,d+f,e,d+f-m),b.lineTo(e,d+m),b.quadraticCurveTo(e,d,e+g,d),b.closePath());return new a.BoundingBox(e,d,e+c,d+f)}};a.Element.rect.prototype=new a.Element.PathElementBase;a.Element.circle=function(c){this.base=
a.Element.PathElementBase;this.base(c);this.path=function(b){var e=this.attribute("cx").toPixels("x"),d=this.attribute("cy").toPixels("y"),c=this.attribute("r").toPixels();null!=b&&(b.beginPath(),b.arc(e,d,c,0,2*Math.PI,!0),b.closePath());return new a.BoundingBox(e-c,d-c,e+c,d+c)}};a.Element.circle.prototype=new a.Element.PathElementBase;a.Element.ellipse=function(c){this.base=a.Element.PathElementBase;this.base(c);this.path=function(b){var e=(Math.sqrt(2)-1)/3*4,d=this.attribute("rx").toPixels("x"),
c=this.attribute("ry").toPixels("y"),f=this.attribute("cx").toPixels("x"),g=this.attribute("cy").toPixels("y");null!=b&&(b.beginPath(),b.moveTo(f,g-c),b.bezierCurveTo(f+e*d,g-c,f+d,g-e*c,f+d,g),b.bezierCurveTo(f+d,g+e*c,f+e*d,g+c,f,g+c),b.bezierCurveTo(f-e*d,g+c,f-d,g+e*c,f-d,g),b.bezierCurveTo(f-d,g-e*c,f-e*d,g-c,f,g-c),b.closePath());return new a.BoundingBox(f-d,g-c,f+d,g+c)}};a.Element.ellipse.prototype=new a.Element.PathElementBase;a.Element.line=function(c){this.base=a.Element.PathElementBase;
this.base(c);this.getPoints=function(){return[new a.Point(this.attribute("x1").toPixels("x"),this.attribute("y1").toPixels("y")),new a.Point(this.attribute("x2").toPixels("x"),this.attribute("y2").toPixels("y"))]};this.path=function(b){var e=this.getPoints();null!=b&&(b.beginPath(),b.moveTo(e[0].x,e[0].y),b.lineTo(e[1].x,e[1].y));return new a.BoundingBox(e[0].x,e[0].y,e[1].x,e[1].y)};this.getMarkers=function(){var a=this.getPoints(),e=a[0].angleTo(a[1]);return[[a[0],e],[a[1],e]]}};a.Element.line.prototype=
new a.Element.PathElementBase;a.Element.polyline=function(c){this.base=a.Element.PathElementBase;this.base(c);this.points=a.CreatePath(this.attribute("points").value);this.path=function(b){var e=new a.BoundingBox(this.points[0].x,this.points[0].y);null!=b&&(b.beginPath(),b.moveTo(this.points[0].x,this.points[0].y));for(var d=1;d<this.points.length;d++)e.addPoint(this.points[d].x,this.points[d].y),null!=b&&b.lineTo(this.points[d].x,this.points[d].y);return e};this.getMarkers=function(){for(var a=[],
e=0;e<this.points.length-1;e++)a.push([this.points[e],this.points[e].angleTo(this.points[e+1])]);a.push([this.points[this.points.length-1],a[a.length-1][1]]);return a}};a.Element.polyline.prototype=new a.Element.PathElementBase;a.Element.polygon=function(c){this.base=a.Element.polyline;this.base(c);this.basePath=this.path;this.path=function(a){var e=this.basePath(a);null!=a&&(a.lineTo(this.points[0].x,this.points[0].y),a.closePath());return e}};a.Element.polygon.prototype=new a.Element.polyline;a.Element.path=
function(c){this.base=a.Element.PathElementBase;this.base(c);c=this.attribute("d").value;c=c.replace(/,/gm," ");for(var b=0;2>b;b++)c=c.replace(/([MmZzLlHhVvCcSsQqTtAa])([^\s])/gm,"$1 $2");c=c.replace(/([^\s])([MmZzLlHhVvCcSsQqTtAa])/gm,"$1 $2");c=c.replace(/([0-9])([+\-])/gm,"$1 $2");for(b=0;2>b;b++)c=c.replace(/(\.[0-9]*)(\.)/gm,"$1 $2");c=c.replace(/([Aa](\s+[0-9]+){3})\s+([01])\s*([01])/gm,"$1 $3 $4 ");c=a.compressSpaces(c);c=a.trim(c);this.PathParser=new function(b){this.tokens=b.split(" ");
this.reset=function(){this.i=-1;this.previousCommand=this.command="";this.start=new a.Point(0,0);this.control=new a.Point(0,0);this.current=new a.Point(0,0);this.points=[];this.angles=[]};this.isEnd=function(){return this.i>=this.tokens.length-1};this.isCommandOrEnd=function(){return this.isEnd()?!0:null!=this.tokens[this.i+1].match(/^[A-Za-z]$/)};this.isRelativeCommand=function(){switch(this.command){case "m":case "l":case "h":case "v":case "c":case "s":case "q":case "t":case "a":case "z":return!0}return!1};
this.getToken=function(){this.i++;return this.tokens[this.i]};this.getScalar=function(){return parseFloat(this.getToken())};this.nextCommand=function(){this.previousCommand=this.command;this.command=this.getToken()};this.getPoint=function(){var b=new a.Point(this.getScalar(),this.getScalar());return this.makeAbsolute(b)};this.getAsControlPoint=function(){var a=this.getPoint();return this.control=a};this.getAsCurrentPoint=function(){var a=this.getPoint();return this.current=a};this.getReflectedControlPoint=
function(){return"c"!=this.previousCommand.toLowerCase()&&"s"!=this.previousCommand.toLowerCase()&&"q"!=this.previousCommand.toLowerCase()&&"t"!=this.previousCommand.toLowerCase()?this.current:new a.Point(2*this.current.x-this.control.x,2*this.current.y-this.control.y)};this.makeAbsolute=function(a){this.isRelativeCommand()&&(a.x+=this.current.x,a.y+=this.current.y);return a};this.addMarker=function(a,b,e){null!=e&&0<this.angles.length&&null==this.angles[this.angles.length-1]&&(this.angles[this.angles.length-
1]=this.points[this.points.length-1].angleTo(e));this.addMarkerAngle(a,null==b?null:b.angleTo(a))};this.addMarkerAngle=function(a,b){this.points.push(a);this.angles.push(b)};this.getMarkerPoints=function(){return this.points};this.getMarkerAngles=function(){for(var a=0;a<this.angles.length;a++)if(null==this.angles[a])for(var b=a+1;b<this.angles.length;b++)if(null!=this.angles[b]){this.angles[a]=this.angles[b];break}return this.angles}}(c);this.path=function(b){var d=this.PathParser;d.reset();var c=
new a.BoundingBox;for(null!=b&&b.beginPath();!d.isEnd();)switch(d.nextCommand(),d.command){case "M":case "m":var f=d.getAsCurrentPoint();d.addMarker(f);c.addPoint(f.x,f.y);null!=b&&b.moveTo(f.x,f.y);for(d.start=d.current;!d.isCommandOrEnd();)f=d.getAsCurrentPoint(),d.addMarker(f,d.start),c.addPoint(f.x,f.y),null!=b&&b.lineTo(f.x,f.y);break;case "L":case "l":for(;!d.isCommandOrEnd();){var g=d.current,f=d.getAsCurrentPoint();d.addMarker(f,g);c.addPoint(f.x,f.y);null!=b&&b.lineTo(f.x,f.y)}break;case "H":case "h":for(;!d.isCommandOrEnd();)f=
new a.Point((d.isRelativeCommand()?d.current.x:0)+d.getScalar(),d.current.y),d.addMarker(f,d.current),d.current=f,c.addPoint(d.current.x,d.current.y),null!=b&&b.lineTo(d.current.x,d.current.y);break;case "V":case "v":for(;!d.isCommandOrEnd();)f=new a.Point(d.current.x,(d.isRelativeCommand()?d.current.y:0)+d.getScalar()),d.addMarker(f,d.current),d.current=f,c.addPoint(d.current.x,d.current.y),null!=b&&b.lineTo(d.current.x,d.current.y);break;case "C":case "c":for(;!d.isCommandOrEnd();){var m=d.current,
g=d.getPoint(),n=d.getAsControlPoint(),f=d.getAsCurrentPoint();d.addMarker(f,n,g);c.addBezierCurve(m.x,m.y,g.x,g.y,n.x,n.y,f.x,f.y);null!=b&&b.bezierCurveTo(g.x,g.y,n.x,n.y,f.x,f.y)}break;case "S":case "s":for(;!d.isCommandOrEnd();)m=d.current,g=d.getReflectedControlPoint(),n=d.getAsControlPoint(),f=d.getAsCurrentPoint(),d.addMarker(f,n,g),c.addBezierCurve(m.x,m.y,g.x,g.y,n.x,n.y,f.x,f.y),null!=b&&b.bezierCurveTo(g.x,g.y,n.x,n.y,f.x,f.y);break;case "Q":case "q":for(;!d.isCommandOrEnd();)m=d.current,
n=d.getAsControlPoint(),f=d.getAsCurrentPoint(),d.addMarker(f,n,n),c.addQuadraticCurve(m.x,m.y,n.x,n.y,f.x,f.y),null!=b&&b.quadraticCurveTo(n.x,n.y,f.x,f.y);break;case "T":case "t":for(;!d.isCommandOrEnd();)m=d.current,n=d.getReflectedControlPoint(),d.control=n,f=d.getAsCurrentPoint(),d.addMarker(f,n,n),c.addQuadraticCurve(m.x,m.y,n.x,n.y,f.x,f.y),null!=b&&b.quadraticCurveTo(n.x,n.y,f.x,f.y);break;case "A":case "a":for(;!d.isCommandOrEnd();){var m=d.current,r=d.getScalar(),h=d.getScalar(),g=d.getScalar()*
(Math.PI/180),p=d.getScalar(),n=d.getScalar(),f=d.getAsCurrentPoint(),l=new a.Point(Math.cos(g)*(m.x-f.x)/2+Math.sin(g)*(m.y-f.y)/2,-Math.sin(g)*(m.x-f.x)/2+Math.cos(g)*(m.y-f.y)/2),v=Math.pow(l.x,2)/Math.pow(r,2)+Math.pow(l.y,2)/Math.pow(h,2);1<v&&(r*=Math.sqrt(v),h*=Math.sqrt(v));p=(p==n?-1:1)*Math.sqrt((Math.pow(r,2)*Math.pow(h,2)-Math.pow(r,2)*Math.pow(l.y,2)-Math.pow(h,2)*Math.pow(l.x,2))/(Math.pow(r,2)*Math.pow(l.y,2)+Math.pow(h,2)*Math.pow(l.x,2)));isNaN(p)&&(p=0);var q=new a.Point(p*r*l.y/
h,p*-h*l.x/r),m=new a.Point((m.x+f.x)/2+Math.cos(g)*q.x-Math.sin(g)*q.y,(m.y+f.y)/2+Math.sin(g)*q.x+Math.cos(g)*q.y),w=function(a,b){return(a[0]*b[0]+a[1]*b[1])/(Math.sqrt(Math.pow(a[0],2)+Math.pow(a[1],2))*Math.sqrt(Math.pow(b[0],2)+Math.pow(b[1],2)))},x=function(a,b){return(a[0]*b[1]<a[1]*b[0]?-1:1)*Math.acos(w(a,b))},p=x([1,0],[(l.x-q.x)/r,(l.y-q.y)/h]),v=[(l.x-q.x)/r,(l.y-q.y)/h],q=[(-l.x-q.x)/r,(-l.y-q.y)/h],l=x(v,q);-1>=w(v,q)&&(l=Math.PI);1<=w(v,q)&&(l=0);v=1-n?1:-1;q=p+l/2*v;x=new a.Point(m.x+
r*Math.cos(q),m.y+h*Math.sin(q));d.addMarkerAngle(x,q-v*Math.PI/2);d.addMarkerAngle(f,q-v*Math.PI);c.addPoint(f.x,f.y);null!=b&&(w=r>h?r:h,f=r>h?1:r/h,r=r>h?h/r:1,b.translate(m.x,m.y),b.rotate(g),b.scale(f,r),b.arc(0,0,w,p,p+l,1-n),b.scale(1/f,1/r),b.rotate(-g),b.translate(-m.x,-m.y))}break;case "Z":case "z":null!=b&&b.closePath(),d.current=d.start}return c};this.getMarkers=function(){for(var a=this.PathParser.getMarkerPoints(),b=this.PathParser.getMarkerAngles(),c=[],f=0;f<a.length;f++)c.push([a[f],
b[f]]);return c}};a.Element.path.prototype=new a.Element.PathElementBase;a.Element.pattern=function(c){this.base=a.Element.ElementBase;this.base(c);this.createPattern=function(b,e){var d=this.attribute("width").toPixels("x",!0),c=this.attribute("height").toPixels("y",!0),f=new a.Element.svg;f.attributes.viewBox=new a.Property("viewBox",this.attribute("viewBox").value);f.attributes.width=new a.Property("width",d+"px");f.attributes.height=new a.Property("height",c+"px");f.attributes.transform=new a.Property("transform",
this.attribute("patternTransform").value);f.children=this.children;var g=document.createElement("canvas");g.width=d;g.height=c;d=g.getContext("2d");this.attribute("x").hasValue()&&this.attribute("y").hasValue()&&d.translate(this.attribute("x").toPixels("x",!0),this.attribute("y").toPixels("y",!0));for(c=-1;1>=c;c++)for(var m=-1;1>=m;m++)d.save(),f.attributes.x=new a.Property("x",c*g.width),f.attributes.y=new a.Property("y",m*g.height),f.render(d),d.restore();return b.createPattern(g,"repeat")}};a.Element.pattern.prototype=
new a.Element.ElementBase;a.Element.marker=function(c){this.base=a.Element.ElementBase;this.base(c);this.baseRender=this.render;this.render=function(b,e,d){b.translate(e.x,e.y);"auto"==this.attribute("orient").valueOrDefault("auto")&&b.rotate(d);"strokeWidth"==this.attribute("markerUnits").valueOrDefault("strokeWidth")&&b.scale(b.lineWidth,b.lineWidth);b.save();var c=new a.Element.svg;c.attributes.viewBox=new a.Property("viewBox",this.attribute("viewBox").value);c.attributes.refX=new a.Property("refX",
this.attribute("refX").value);c.attributes.refY=new a.Property("refY",this.attribute("refY").value);c.attributes.width=new a.Property("width",this.attribute("markerWidth").value);c.attributes.height=new a.Property("height",this.attribute("markerHeight").value);c.attributes.fill=new a.Property("fill",this.attribute("fill").valueOrDefault("black"));c.attributes.stroke=new a.Property("stroke",this.attribute("stroke").valueOrDefault("none"));c.children=this.children;c.render(b);b.restore();"strokeWidth"==
this.attribute("markerUnits").valueOrDefault("strokeWidth")&&b.scale(1/b.lineWidth,1/b.lineWidth);"auto"==this.attribute("orient").valueOrDefault("auto")&&b.rotate(-d);b.translate(-e.x,-e.y)}};a.Element.marker.prototype=new a.Element.ElementBase;a.Element.defs=function(c){this.base=a.Element.ElementBase;this.base(c);this.render=function(a){}};a.Element.defs.prototype=new a.Element.ElementBase;a.Element.GradientBase=function(c){this.base=a.Element.ElementBase;this.base(c);this.stops=[];for(c=0;c<this.children.length;c++){var b=
this.children[c];"stop"==b.type&&this.stops.push(b)}this.getGradient=function(){};this.gradientUnits=function(){return this.attribute("gradientUnits").valueOrDefault("objectBoundingBox")};this.attributesToInherit=["gradientUnits"];this.inheritStopContainer=function(a){for(var b=0;b<this.attributesToInherit.length;b++){var c=this.attributesToInherit[b];!this.attribute(c).hasValue()&&a.attribute(c).hasValue()&&(this.attribute(c,!0).value=a.attribute(c).value)}};this.createGradient=function(b,d,c){var f=
this;this.getHrefAttribute().hasValue()&&(f=this.getHrefAttribute().getDefinition(),this.inheritStopContainer(f));var g=function(b){return c.hasValue()?(new a.Property("color",b)).addOpacity(c).value:b};b=this.getGradient(b,d);if(null==b)return g(f.stops[f.stops.length-1].color);for(d=0;d<f.stops.length;d++)b.addColorStop(f.stops[d].offset,g(f.stops[d].color));return this.attribute("gradientTransform").hasValue()?(f=a.ViewPort.viewPorts[0],g=new a.Element.rect,g.attributes.x=new a.Property("x",-a.MAX_VIRTUAL_PIXELS/
3),g.attributes.y=new a.Property("y",-a.MAX_VIRTUAL_PIXELS/3),g.attributes.width=new a.Property("width",a.MAX_VIRTUAL_PIXELS),g.attributes.height=new a.Property("height",a.MAX_VIRTUAL_PIXELS),d=new a.Element.g,d.attributes.transform=new a.Property("transform",this.attribute("gradientTransform").value),d.children=[g],g=new a.Element.svg,g.attributes.x=new a.Property("x",0),g.attributes.y=new a.Property("y",0),g.attributes.width=new a.Property("width",f.width),g.attributes.height=new a.Property("height",
f.height),g.children=[d],d=document.createElement("canvas"),d.width=f.width,d.height=f.height,f=d.getContext("2d"),f.fillStyle=b,g.render(f),f.createPattern(d,"no-repeat")):b}};a.Element.GradientBase.prototype=new a.Element.ElementBase;a.Element.linearGradient=function(c){this.base=a.Element.GradientBase;this.base(c);this.attributesToInherit.push("x1");this.attributesToInherit.push("y1");this.attributesToInherit.push("x2");this.attributesToInherit.push("y2");this.getGradient=function(a,e){var c="objectBoundingBox"==
this.gradientUnits()?e.getBoundingBox():null;this.attribute("x1").hasValue()||this.attribute("y1").hasValue()||this.attribute("x2").hasValue()||this.attribute("y2").hasValue()||(this.attribute("x1",!0).value=0,this.attribute("y1",!0).value=0,this.attribute("x2",!0).value=1,this.attribute("y2",!0).value=0);var k="objectBoundingBox"==this.gradientUnits()?c.x()+c.width()*this.attribute("x1").numValue():this.attribute("x1").toPixels("x"),f="objectBoundingBox"==this.gradientUnits()?c.y()+c.height()*this.attribute("y1").numValue():
this.attribute("y1").toPixels("y"),g="objectBoundingBox"==this.gradientUnits()?c.x()+c.width()*this.attribute("x2").numValue():this.attribute("x2").toPixels("x"),c="objectBoundingBox"==this.gradientUnits()?c.y()+c.height()*this.attribute("y2").numValue():this.attribute("y2").toPixels("y");return k==g&&f==c?null:a.createLinearGradient(k,f,g,c)}};a.Element.linearGradient.prototype=new a.Element.GradientBase;a.Element.radialGradient=function(c){this.base=a.Element.GradientBase;this.base(c);this.attributesToInherit.push("cx");
this.attributesToInherit.push("cy");this.attributesToInherit.push("r");this.attributesToInherit.push("fx");this.attributesToInherit.push("fy");this.getGradient=function(a,c){var d=c.getBoundingBox();this.attribute("cx").hasValue()||(this.attribute("cx",!0).value="50%");this.attribute("cy").hasValue()||(this.attribute("cy",!0).value="50%");this.attribute("r").hasValue()||(this.attribute("r",!0).value="50%");var k="objectBoundingBox"==this.gradientUnits()?d.x()+d.width()*this.attribute("cx").numValue():
this.attribute("cx").toPixels("x"),f="objectBoundingBox"==this.gradientUnits()?d.y()+d.height()*this.attribute("cy").numValue():this.attribute("cy").toPixels("y"),g=k,m=f;this.attribute("fx").hasValue()&&(g="objectBoundingBox"==this.gradientUnits()?d.x()+d.width()*this.attribute("fx").numValue():this.attribute("fx").toPixels("x"));this.attribute("fy").hasValue()&&(m="objectBoundingBox"==this.gradientUnits()?d.y()+d.height()*this.attribute("fy").numValue():this.attribute("fy").toPixels("y"));d="objectBoundingBox"==
this.gradientUnits()?(d.width()+d.height())/2*this.attribute("r").numValue():this.attribute("r").toPixels();return a.createRadialGradient(g,m,0,k,f,d)}};a.Element.radialGradient.prototype=new a.Element.GradientBase;a.Element.stop=function(c){this.base=a.Element.ElementBase;this.base(c);this.offset=this.attribute("offset").numValue();0>this.offset&&(this.offset=0);1<this.offset&&(this.offset=1);c=this.style("stop-color",!0);""===c.value&&(c.value="#000");this.style("stop-opacity").hasValue()&&(c=c.addOpacity(this.style("stop-opacity")));
this.color=c.value};a.Element.stop.prototype=new a.Element.ElementBase;a.Element.AnimateBase=function(c){this.base=a.Element.ElementBase;this.base(c);a.Animations.push(this);this.duration=0;this.begin=this.attribute("begin").toMilliseconds();this.maxDuration=this.begin+this.attribute("dur").toMilliseconds();this.getProperty=function(){var a=this.attribute("attributeType").value,c=this.attribute("attributeName").value;return"CSS"==a?this.parent.style(c,!0):this.parent.attribute(c,!0)};this.initialValue=
null;this.initialUnits="";this.removed=!1;this.calcValue=function(){return""};this.update=function(a){null==this.initialValue&&(this.initialValue=this.getProperty().value,this.initialUnits=this.getProperty().getUnits());if(this.duration>this.maxDuration){if("indefinite"==this.attribute("repeatCount").value||"indefinite"==this.attribute("repeatDur").value)this.duration=0;else if("freeze"==this.attribute("fill").valueOrDefault("remove")&&!this.frozen)this.frozen=!0,this.parent.animationFrozen=!0,this.parent.animationFrozenValue=
this.getProperty().value;else if("remove"==this.attribute("fill").valueOrDefault("remove")&&!this.removed)return this.removed=!0,this.getProperty().value=this.parent.animationFrozen?this.parent.animationFrozenValue:this.initialValue,!0;return!1}this.duration+=a;a=!1;this.begin<this.duration&&(a=this.calcValue(),this.attribute("type").hasValue()&&(a=this.attribute("type").value+"("+a+")"),this.getProperty().value=a,a=!0);return a};this.from=this.attribute("from");this.to=this.attribute("to");this.values=
this.attribute("values");this.values.hasValue()&&(this.values.value=this.values.value.split(";"));this.progress=function(){var b={progress:(this.duration-this.begin)/(this.maxDuration-this.begin)};if(this.values.hasValue()){var c=b.progress*(this.values.value.length-1),d=Math.floor(c),k=Math.ceil(c);b.from=new a.Property("from",parseFloat(this.values.value[d]));b.to=new a.Property("to",parseFloat(this.values.value[k]));b.progress=(c-d)/(k-d)}else b.from=this.from,b.to=this.to;return b}};a.Element.AnimateBase.prototype=
new a.Element.ElementBase;a.Element.animate=function(c){this.base=a.Element.AnimateBase;this.base(c);this.calcValue=function(){var a=this.progress();return a.from.numValue()+(a.to.numValue()-a.from.numValue())*a.progress+this.initialUnits}};a.Element.animate.prototype=new a.Element.AnimateBase;a.Element.animateColor=function(c){this.base=a.Element.AnimateBase;this.base(c);this.calcValue=function(){var a=this.progress(),c=new x(a.from.value),d=new x(a.to.value);if(c.ok&&d.ok){var k=c.g+(d.g-c.g)*a.progress,
f=c.b+(d.b-c.b)*a.progress;return"rgb("+parseInt(c.r+(d.r-c.r)*a.progress,10)+","+parseInt(k,10)+","+parseInt(f,10)+")"}return this.attribute("from").value}};a.Element.animateColor.prototype=new a.Element.AnimateBase;a.Element.animateTransform=function(c){this.base=a.Element.AnimateBase;this.base(c);this.calcValue=function(){for(var b=this.progress(),c=a.ToNumberArray(b.from.value),d=a.ToNumberArray(b.to.value),k="",f=0;f<c.length;f++)k+=c[f]+(d[f]-c[f])*b.progress+" ";return k}};a.Element.animateTransform.prototype=
new a.Element.animate;a.Element.font=function(c){this.base=a.Element.ElementBase;this.base(c);this.horizAdvX=this.attribute("horiz-adv-x").numValue();this.isArabic=this.isRTL=!1;this.missingGlyph=this.fontFace=null;this.glyphs=[];for(c=0;c<this.children.length;c++){var b=this.children[c];"font-face"==b.type?(this.fontFace=b,b.style("font-family").hasValue()&&(a.Definitions[b.style("font-family").value]=this)):"missing-glyph"==b.type?this.missingGlyph=b:"glyph"==b.type&&(""!=b.arabicForm?(this.isArabic=
this.isRTL=!0,"undefined"==typeof this.glyphs[b.unicode]&&(this.glyphs[b.unicode]=[]),this.glyphs[b.unicode][b.arabicForm]=b):this.glyphs[b.unicode]=b)}};a.Element.font.prototype=new a.Element.ElementBase;a.Element.fontface=function(c){this.base=a.Element.ElementBase;this.base(c);this.ascent=this.attribute("ascent").value;this.descent=this.attribute("descent").value;this.unitsPerEm=this.attribute("units-per-em").numValue()};a.Element.fontface.prototype=new a.Element.ElementBase;a.Element.missingglyph=
function(c){this.base=a.Element.path;this.base(c);this.horizAdvX=0};a.Element.missingglyph.prototype=new a.Element.path;a.Element.glyph=function(c){this.base=a.Element.path;this.base(c);this.horizAdvX=this.attribute("horiz-adv-x").numValue();this.unicode=this.attribute("unicode").value;this.arabicForm=this.attribute("arabic-form").value};a.Element.glyph.prototype=new a.Element.path;a.Element.text=function(c){this.captureTextNodes=!0;this.base=a.Element.RenderedElementBase;this.base(c);this.baseSetContext=
this.setContext;this.setContext=function(a){this.baseSetContext(a);var c=this.style("dominant-baseline").toTextBaseline();null==c&&(c=this.style("alignment-baseline").toTextBaseline());null!=c&&(a.textBaseline=c)};this.getBoundingBox=function(){var b=this.attribute("x").toPixels("x"),c=this.attribute("y").toPixels("y"),d=this.parent.style("font-size").numValueOrDefault(a.Font.Parse(a.ctx.font).fontSize);return new a.BoundingBox(b,c-d,b+Math.floor(2*d/3)*this.children[0].getText().length,c)};this.renderChildren=
function(a){this.x=this.attribute("x").toPixels("x");this.y=this.attribute("y").toPixels("y");this.attribute("dx").hasValue()&&(this.x+=this.attribute("dx").toPixels("x"));this.attribute("dy").hasValue()&&(this.y+=this.attribute("dy").toPixels("y"));this.x+=this.getAnchorDelta(a,this,0);for(var c=0;c<this.children.length;c++)this.renderChild(a,this,c)};this.getAnchorDelta=function(a,c,d){var k=this.style("text-anchor").valueOrDefault("start");if("start"!=k){for(var f=0,g=d;g<c.children.length;g++){var m=
c.children[g];if(g>d&&m.attribute("x").hasValue())break;f+=m.measureTextRecursive(a)}return-1*("end"==k?f:f/2)}return 0};this.renderChild=function(a,c,d){var k=c.children[d];k.attribute("x").hasValue()?(k.x=k.attribute("x").toPixels("x")+c.getAnchorDelta(a,c,d),k.attribute("dx").hasValue()&&(k.x+=k.attribute("dx").toPixels("x"))):(k.attribute("dx").hasValue()&&(c.x+=k.attribute("dx").toPixels("x")),k.x=c.x);c.x=k.x+k.measureText(a);k.attribute("y").hasValue()?(k.y=k.attribute("y").toPixels("y"),k.attribute("dy").hasValue()&&
(k.y+=k.attribute("dy").toPixels("y"))):(k.attribute("dy").hasValue()&&(c.y+=k.attribute("dy").toPixels("y")),k.y=c.y);c.y=k.y;k.render(a);for(d=0;d<k.children.length;d++)c.renderChild(a,k,d)}};a.Element.text.prototype=new a.Element.RenderedElementBase;a.Element.TextElementBase=function(c){this.base=a.Element.RenderedElementBase;this.base(c);this.getGlyph=function(a,c,d){var k=c[d],f=null;if(a.isArabic){var g="isolated";(0==d||" "==c[d-1])&&d<c.length-2&&" "!=c[d+1]&&(g="terminal");0<d&&" "!=c[d-
1]&&d<c.length-2&&" "!=c[d+1]&&(g="medial");0<d&&" "!=c[d-1]&&(d==c.length-1||" "==c[d+1])&&(g="initial");"undefined"!=typeof a.glyphs[k]&&(f=a.glyphs[k][g],null==f&&"glyph"==a.glyphs[k].type&&(f=a.glyphs[k]))}else f=a.glyphs[k];null==f&&(f=a.missingGlyph);return f};this.renderChildren=function(b){var c=this.parent.style("font-family").getDefinition();if(null!=c){var d=this.parent.style("font-size").numValueOrDefault(a.Font.Parse(a.ctx.font).fontSize),k=this.parent.style("font-style").valueOrDefault(a.Font.Parse(a.ctx.font).fontStyle),
f=this.getText();c.isRTL&&(f=f.split("").reverse().join(""));for(var g=a.ToNumberArray(this.parent.attribute("dx").value),m=0;m<f.length;m++){var n=this.getGlyph(c,f,m),h=d/c.fontFace.unitsPerEm;b.translate(this.x,this.y);b.scale(h,-h);var l=b.lineWidth;b.lineWidth=b.lineWidth*c.fontFace.unitsPerEm/d;"italic"==k&&b.transform(1,0,.4,1,0,0);n.render(b);"italic"==k&&b.transform(1,0,-.4,1,0,0);b.lineWidth=l;b.scale(1/h,-1/h);b.translate(-this.x,-this.y);this.x+=d*(n.horizAdvX||c.horizAdvX)/c.fontFace.unitsPerEm;
"undefined"==typeof g[m]||isNaN(g[m])||(this.x+=g[m])}}else""!=b.fillStyle&&b.fillText(a.compressSpaces(this.getText()),this.x,this.y),""!=b.strokeStyle&&b.strokeText(a.compressSpaces(this.getText()),this.x,this.y)};this.getText=function(){};this.measureTextRecursive=function(a){for(var c=this.measureText(a),d=0;d<this.children.length;d++)c+=this.children[d].measureTextRecursive(a);return c};this.measureText=function(b){var c=this.parent.style("font-family").getDefinition();if(null!=c){b=this.parent.style("font-size").numValueOrDefault(a.Font.Parse(a.ctx.font).fontSize);
var d=0,k=this.getText();c.isRTL&&(k=k.split("").reverse().join(""));for(var f=a.ToNumberArray(this.parent.attribute("dx").value),g=0;g<k.length;g++){var m=this.getGlyph(c,k,g),d=d+(m.horizAdvX||c.horizAdvX)*b/c.fontFace.unitsPerEm;"undefined"==typeof f[g]||isNaN(f[g])||(d+=f[g])}return d}c=a.compressSpaces(this.getText());if(!b.measureText)return 10*c.length;b.save();this.setContext(b);c=b.measureText(c).width;b.restore();return c}};a.Element.TextElementBase.prototype=new a.Element.RenderedElementBase;
a.Element.tspan=function(c){this.captureTextNodes=!0;this.base=a.Element.TextElementBase;this.base(c);this.text=a.compressSpaces(c.value||c.text||c.textContent||"");this.getText=function(){return 0<this.children.length?"":this.text}};a.Element.tspan.prototype=new a.Element.TextElementBase;a.Element.tref=function(c){this.base=a.Element.TextElementBase;this.base(c);this.getText=function(){var a=this.getHrefAttribute().getDefinition();if(null!=a)return a.children[0].getText()}};a.Element.tref.prototype=
new a.Element.TextElementBase;a.Element.a=function(c){this.base=a.Element.TextElementBase;this.base(c);this.hasText=0<c.childNodes.length;for(var b=0;b<c.childNodes.length;b++)3!=c.childNodes[b].nodeType&&(this.hasText=!1);this.text=this.hasText?c.childNodes[0].value:"";this.getText=function(){return this.text};this.baseRenderChildren=this.renderChildren;this.renderChildren=function(b){if(this.hasText){this.baseRenderChildren(b);var c=new a.Property("fontSize",a.Font.Parse(a.ctx.font).fontSize);a.Mouse.checkBoundingBox(this,
new a.BoundingBox(this.x,this.y-c.toPixels("y"),this.x+this.measureText(b),this.y))}else 0<this.children.length&&(c=new a.Element.g,c.children=this.children,c.parent=this,c.render(b))};this.onclick=function(){window.open(this.getHrefAttribute().value)};this.onmousemove=function(){a.ctx.canvas.style.cursor="pointer"}};a.Element.a.prototype=new a.Element.TextElementBase;a.Element.image=function(c){this.base=a.Element.RenderedElementBase;this.base(c);var b=this.getHrefAttribute().value;if(""!=b){var e=
b.match(/\.svg$/);a.Images.push(this);this.loaded=!1;if(e)this.img=a.ajax(b),this.loaded=!0;else{this.img=document.createElement("img");1==a.opts.useCORS&&(this.img.crossOrigin="Anonymous");var d=this;this.img.onload=function(){d.loaded=!0};this.img.onerror=function(){a.log('ERROR: image "'+b+'" not found');d.loaded=!0};this.img.src=b}this.renderChildren=function(b){var c=this.attribute("x").toPixels("x"),d=this.attribute("y").toPixels("y"),m=this.attribute("width").toPixels("x"),n=this.attribute("height").toPixels("y");
0!=m&&0!=n&&(b.save(),e?b.drawSvg(this.img,c,d,m,n):(b.translate(c,d),a.AspectRatio(b,this.attribute("preserveAspectRatio").value,m,this.img.width,n,this.img.height,0,0),b.drawImage(this.img,0,0)),b.restore())};this.getBoundingBox=function(){var b=this.attribute("x").toPixels("x"),c=this.attribute("y").toPixels("y"),d=this.attribute("width").toPixels("x"),e=this.attribute("height").toPixels("y");return new a.BoundingBox(b,c,b+d,c+e)}}};a.Element.image.prototype=new a.Element.RenderedElementBase;a.Element.g=
function(c){this.base=a.Element.RenderedElementBase;this.base(c);this.getBoundingBox=function(){for(var b=new a.BoundingBox,c=0;c<this.children.length;c++)b.addBoundingBox(this.children[c].getBoundingBox());return b}};a.Element.g.prototype=new a.Element.RenderedElementBase;a.Element.symbol=function(c){this.base=a.Element.RenderedElementBase;this.base(c);this.render=function(a){}};a.Element.symbol.prototype=new a.Element.RenderedElementBase;a.Element.style=function(c){this.base=a.Element.ElementBase;
this.base(c);for(var b="",e=0;e<c.childNodes.length;e++)b+=c.childNodes[e].data;b=b.replace(/(\/\*([^*]|[\r\n]|(\*+([^*\/]|[\r\n])))*\*+\/)|(^[\s]*\/\/.*)/gm,"");b=a.compressSpaces(b);c=b.split("}");for(e=0;e<c.length;e++)if(""!=a.trim(c[e]))for(var d=c[e].split("{"),b=d[0].split(","),d=d[1].split(";"),k=0;k<b.length;k++){var f=a.trim(b[k]);if(""!=f){for(var g=a.Styles[f]||{},m=0;m<d.length;m++){var n=d[m].indexOf(":"),h=d[m].substr(0,n),n=d[m].substr(n+1,d[m].length-n);null!=h&&null!=n&&(g[a.trim(h)]=
new a.Property(a.trim(h),a.trim(n)))}a.Styles[f]=g;a.StylesSpecificity[f]=A(f);if("@font-face"==f)for(f=g["font-family"].value.replace(/"/g,""),g=g.src.value.split(","),m=0;m<g.length;m++)if(0<g[m].indexOf('format("svg")'))for(h=g[m].indexOf("url"),n=g[m].indexOf(")",h),h=g[m].substr(h+5,n-h-6),h=a.parseXml(a.ajax(h)).getElementsByTagName("font"),n=0;n<h.length;n++){var l=a.CreateElement(h[n]);a.Definitions[f]=l}}}};a.Element.style.prototype=new a.Element.ElementBase;a.Element.use=function(c){this.base=
a.Element.RenderedElementBase;this.base(c);this.baseSetContext=this.setContext;this.setContext=function(a){this.baseSetContext(a);this.attribute("x").hasValue()&&a.translate(this.attribute("x").toPixels("x"),0);this.attribute("y").hasValue()&&a.translate(0,this.attribute("y").toPixels("y"))};var b=this.getHrefAttribute().getDefinition();this.path=function(a){null!=b&&b.path(a)};this.getBoundingBox=function(){if(null!=b)return b.getBoundingBox()};this.renderChildren=function(c){if(null!=b){var d=b;
"symbol"==b.type&&(d=new a.Element.svg,d.type="svg",d.attributes.viewBox=new a.Property("viewBox",b.attribute("viewBox").value),d.attributes.preserveAspectRatio=new a.Property("preserveAspectRatio",b.attribute("preserveAspectRatio").value),d.attributes.overflow=new a.Property("overflow",b.attribute("overflow").value),d.children=b.children);"svg"==d.type&&(this.attribute("width").hasValue()&&(d.attributes.width=new a.Property("width",this.attribute("width").value)),this.attribute("height").hasValue()&&
(d.attributes.height=new a.Property("height",this.attribute("height").value)));var k=d.parent;d.parent=null;d.render(c);d.parent=k}}};a.Element.use.prototype=new a.Element.RenderedElementBase;a.Element.mask=function(c){this.base=a.Element.ElementBase;this.base(c);this.apply=function(b,c){var d=this.attribute("x").toPixels("x"),k=this.attribute("y").toPixels("y"),f=this.attribute("width").toPixels("x"),g=this.attribute("height").toPixels("y");if(0==f&&0==g){g=new a.BoundingBox;for(d=0;d<this.children.length;d++)g.addBoundingBox(this.children[d].getBoundingBox());
d=Math.floor(g.x1);k=Math.floor(g.y1);f=Math.floor(g.width());g=Math.floor(g.height())}var m=c.attribute("mask").value;c.attribute("mask").value="";var n=document.createElement("canvas");n.width=d+f;n.height=k+g;var h=n.getContext("2d");this.renderChildren(h);var l=document.createElement("canvas");l.width=d+f;l.height=k+g;var p=l.getContext("2d");c.render(p);p.globalCompositeOperation="destination-in";p.fillStyle=h.createPattern(n,"no-repeat");p.fillRect(0,0,d+f,k+g);b.fillStyle=p.createPattern(l,
"no-repeat");b.fillRect(0,0,d+f,k+g);c.attribute("mask").value=m};this.render=function(a){}};a.Element.mask.prototype=new a.Element.ElementBase;a.Element.clipPath=function(c){this.base=a.Element.ElementBase;this.base(c);this.apply=function(b){var c=CanvasRenderingContext2D.prototype.beginPath;CanvasRenderingContext2D.prototype.beginPath=function(){};var d=CanvasRenderingContext2D.prototype.closePath;CanvasRenderingContext2D.prototype.closePath=function(){};c.call(b);for(var k=0;k<this.children.length;k++){var f=
this.children[k];if("undefined"!=typeof f.path){var g=null;f.style("transform",!1,!0).hasValue()&&(g=new a.Transform(f.style("transform",!1,!0).value),g.apply(b));f.path(b);CanvasRenderingContext2D.prototype.closePath=d;g&&g.unapply(b)}}d.call(b);b.clip();CanvasRenderingContext2D.prototype.beginPath=c;CanvasRenderingContext2D.prototype.closePath=d};this.render=function(a){}};a.Element.clipPath.prototype=new a.Element.ElementBase;a.Element.filter=function(c){this.base=a.Element.ElementBase;this.base(c);
this.apply=function(a,c){var d=c.getBoundingBox(),k=Math.floor(d.x1),f=Math.floor(d.y1),g=Math.floor(d.width()),d=Math.floor(d.height()),m=c.style("filter").value;c.style("filter").value="";for(var h=0,l=0,u=0;u<this.children.length;u++)var p=this.children[u].extraFilterDistance||0,h=Math.max(h,p),l=Math.max(l,p);p=document.createElement("canvas");p.width=g+2*h;p.height=d+2*l;var t=p.getContext("2d");t.translate(-k+h,-f+l);c.render(t);for(u=0;u<this.children.length;u++)"function"===typeof this.children[u].apply&&
this.children[u].apply(t,0,0,g+2*h,d+2*l);a.drawImage(p,0,0,g+2*h,d+2*l,k-h,f-l,g+2*h,d+2*l);c.style("filter",!0).value=m};this.render=function(a){}};a.Element.filter.prototype=new a.Element.ElementBase;a.Element.feMorphology=function(c){this.base=a.Element.ElementBase;this.base(c);this.apply=function(a,c,d,k,f){}};a.Element.feMorphology.prototype=new a.Element.ElementBase;a.Element.feComposite=function(c){this.base=a.Element.ElementBase;this.base(c);this.apply=function(a,c,d,k,f){}};a.Element.feComposite.prototype=
new a.Element.ElementBase;a.Element.feColorMatrix=function(c){function b(a,b){var c=e[a];return c*(0>c?b-255:b)}this.base=a.Element.ElementBase;this.base(c);var e=a.ToNumberArray(this.attribute("values").value);switch(this.attribute("type").valueOrDefault("matrix")){case "saturate":c=e[0];e=[.213+.787*c,.715-.715*c,.072-.072*c,0,0,.213-.213*c,.715+.285*c,.072-.072*c,0,0,.213-.213*c,.715-.715*c,.072+.928*c,0,0,0,0,0,1,0,0,0,0,0,1];break;case "hueRotate":var d=e[0]*Math.PI/180;c=function(a,b,c){return a+
Math.cos(d)*b+Math.sin(d)*c};e=[c(.213,.787,-.213),c(.715,-.715,-.715),c(.072,-.072,.928),0,0,c(.213,-.213,.143),c(.715,.285,.14),c(.072,-.072,-.283),0,0,c(.213,-.213,-.787),c(.715,-.715,.715),c(.072,.928,.072),0,0,0,0,0,1,0,0,0,0,0,1];break;case "luminanceToAlpha":e=[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,.2125,.7154,.0721,0,0,0,0,0,0,1]}this.apply=function(a,c,d,e,h){var l=a.getImageData(0,0,e,h);for(d=0;d<h;d++)for(c=0;c<e;c++){var u=l.data[d*e*4+4*c+0],p=l.data[d*e*4+4*c+1],t=l.data[d*e*4+4*c+2],v=l.data[d*
e*4+4*c+3],q=b(0,u)+b(1,p)+b(2,t)+b(3,v)+b(4,1);l.data[d*e*4+4*c+0]=q;q=b(5,u)+b(6,p)+b(7,t)+b(8,v)+b(9,1);l.data[d*e*4+4*c+1]=q;q=b(10,u)+b(11,p)+b(12,t)+b(13,v)+b(14,1);l.data[d*e*4+4*c+2]=q;u=b(15,u)+b(16,p)+b(17,t)+b(18,v)+b(19,1);l.data[d*e*4+4*c+3]=u}a.clearRect(0,0,e,h);a.putImageData(l,0,0)}};a.Element.feColorMatrix.prototype=new a.Element.ElementBase;a.Element.feGaussianBlur=function(c){this.base=a.Element.ElementBase;this.base(c);this.extraFilterDistance=this.blurRadius=Math.floor(this.attribute("stdDeviation").numValue());
this.apply=function(b,c,d,k,f){"undefined"==typeof y.canvasRGBA?a.log("ERROR: StackBlur.js must be included for blur to work"):(b.canvas.id=a.UniqueId(),b.canvas.style.display="none",document.body.appendChild(b.canvas),y.canvasRGBA(b.canvas.id,c,d,k,f,this.blurRadius),document.body.removeChild(b.canvas))}};a.Element.feGaussianBlur.prototype=new a.Element.ElementBase;a.Element.title=function(a){};a.Element.title.prototype=new a.Element.ElementBase;a.Element.desc=function(a){};a.Element.desc.prototype=
new a.Element.ElementBase;a.Element.MISSING=function(c){a.log("ERROR: Element '"+c.nodeName+"' not yet implemented.")};a.Element.MISSING.prototype=new a.Element.ElementBase;a.CreateElement=function(c){var b=c.nodeName.replace(/^[^:]+:/,""),b=b.replace(/\-/g,""),b="undefined"!=typeof a.Element[b]?new a.Element[b](c):new a.Element.MISSING(c);b.type=c.nodeName;return b};a.load=function(c,b){a.loadXml(c,a.ajax(b))};a.loadXml=function(c,b){a.loadXmlDoc(c,a.parseXml(b))};a.loadXmlDoc=function(c,b){a.init(c);
var e=function(a){for(var b=c.canvas;b;)a.x-=b.offsetLeft,a.y-=b.offsetTop,b=b.offsetParent;window.scrollX&&(a.x+=window.scrollX);window.scrollY&&(a.y+=window.scrollY);return a};1!=a.opts.ignoreMouse&&(c.canvas.onclick=function(b){b=e(new a.Point(null!=b?b.clientX:event.clientX,null!=b?b.clientY:event.clientY));a.Mouse.onclick(b.x,b.y)},c.canvas.onmousemove=function(b){b=e(new a.Point(null!=b?b.clientX:event.clientX,null!=b?b.clientY:event.clientY));a.Mouse.onmousemove(b.x,b.y)});var d=a.CreateElement(b.documentElement);
d.root=!0;d.addStylesFromStyleDefinition();var k=!0,f=function(){a.ViewPort.Clear();c.canvas.parentNode&&a.ViewPort.SetCurrent(c.canvas.parentNode.clientWidth,c.canvas.parentNode.clientHeight);1!=a.opts.ignoreDimensions&&(d.style("width").hasValue()&&(c.canvas.width=d.style("width").toPixels("x"),c.canvas.style.width=c.canvas.width+"px"),d.style("height").hasValue()&&(c.canvas.height=d.style("height").toPixels("y"),c.canvas.style.height=c.canvas.height+"px"));var e=c.canvas.clientWidth||c.canvas.width,
f=c.canvas.clientHeight||c.canvas.height;1==a.opts.ignoreDimensions&&d.style("width").hasValue()&&d.style("height").hasValue()&&(e=d.style("width").toPixels("x"),f=d.style("height").toPixels("y"));a.ViewPort.SetCurrent(e,f);null!=a.opts.offsetX&&(d.attribute("x",!0).value=a.opts.offsetX);null!=a.opts.offsetY&&(d.attribute("y",!0).value=a.opts.offsetY);if(null!=a.opts.scaleWidth||null!=a.opts.scaleHeight){var g=null,h=null,l=a.ToNumberArray(d.attribute("viewBox").value);null!=a.opts.scaleWidth&&(d.attribute("width").hasValue()?
g=d.attribute("width").toPixels("x")/a.opts.scaleWidth:isNaN(l[2])||(g=l[2]/a.opts.scaleWidth));null!=a.opts.scaleHeight&&(d.attribute("height").hasValue()?h=d.attribute("height").toPixels("y")/a.opts.scaleHeight:isNaN(l[3])||(h=l[3]/a.opts.scaleHeight));null==g&&(g=h);null==h&&(h=g);d.attribute("width",!0).value=a.opts.scaleWidth;d.attribute("height",!0).value=a.opts.scaleHeight;d.style("transform",!0,!0).value+=" scale("+1/g+","+1/h+")"}1!=a.opts.ignoreClear&&c.clearRect(0,0,e,f);d.render(c);k&&
(k=!1,"function"==typeof a.opts.renderCallback&&a.opts.renderCallback(b))},g=!0;a.ImagesLoaded()&&(g=!1,f());a.intervalID=setInterval(function(){var b=!1;g&&a.ImagesLoaded()&&(g=!1,b=!0);1!=a.opts.ignoreMouse&&(b|=a.Mouse.hasEvents());if(1!=a.opts.ignoreAnimation)for(var c=0;c<a.Animations.length;c++)b|=a.Animations[c].update(1E3/a.FRAMERATE);"function"==typeof a.opts.forceRedraw&&1==a.opts.forceRedraw()&&(b=!0);b&&(f(),a.Mouse.runEvents())},1E3/a.FRAMERATE)};a.stop=function(){a.intervalID&&clearInterval(a.intervalID)};
a.Mouse=new function(){this.events=[];this.hasEvents=function(){return 0!=this.events.length};this.onclick=function(a,b){this.events.push({type:"onclick",x:a,y:b,run:function(a){if(a.onclick)a.onclick()}})};this.onmousemove=function(a,b){this.events.push({type:"onmousemove",x:a,y:b,run:function(a){if(a.onmousemove)a.onmousemove()}})};this.eventElements=[];this.checkPath=function(a,b){for(var e=0;e<this.events.length;e++){var d=this.events[e];b.isPointInPath&&b.isPointInPath(d.x,d.y)&&(this.eventElements[e]=
a)}};this.checkBoundingBox=function(a,b){for(var e=0;e<this.events.length;e++){var d=this.events[e];b.isPointInBox(d.x,d.y)&&(this.eventElements[e]=a)}};this.runEvents=function(){a.ctx.canvas.style.cursor="";for(var c=0;c<this.events.length;c++)for(var b=this.events[c],e=this.eventElements[c];e;)b.run(e),e=e.parent;this.events=[];this.eventElements=[]}};return a}var z=function(h,a,l){if(null==h&&null==a&&null==l)for(a=document.querySelectorAll("svg"),h=0;h<a.length;h++){l=a[h];var c=document.createElement("canvas");
c.width=l.clientWidth;c.height=l.clientHeight;l.parentNode.insertBefore(c,l);l.parentNode.removeChild(l);var b=document.createElement("div");b.appendChild(l);z(c,b.innerHTML)}else{"string"==typeof h&&(h=document.getElementById(h));null!=h.svg&&h.svg.stop();l=I(l||{});if(1!=h.childNodes.length||"OBJECT"!=h.childNodes[0].nodeName)h.svg=l;h=h.getContext("2d");"undefined"!=typeof a.documentElement?l.loadXmlDoc(h,a):"<"==a.substr(0,1)?l.loadXml(h,a):l.load(h,a)}},w;if("undefined"!=typeof Element.prototype.matches)w=
function(h,a){return h.matches(a)};else if("undefined"!=typeof Element.prototype.webkitMatchesSelector)w=function(h,a){return h.webkitMatchesSelector(a)};else if("undefined"!=typeof Element.prototype.mozMatchesSelector)w=function(h,a){return h.mozMatchesSelector(a)};else if("undefined"!=typeof Element.prototype.msMatchesSelector)w=function(h,a){return h.msMatchesSelector(a)};else if("undefined"!=typeof Element.prototype.oMatchesSelector)w=function(h,a){return h.oMatchesSelector(a)};else{if("function"===
typeof jQuery||"function"===typeof Zepto)w=function(h,a){return $(h).is(a)};"undefined"===typeof w&&(w=Sizzle.matchesSelector)}var B=/(\[[^\]]+\])/g,C=/(#[^\s\+>~\.\[:]+)/g,D=/(\.[^\s\+>~\.\[:]+)/g,E=/(::[^\s\+>~\.\[:]+|:first-line|:first-letter|:before|:after)/gi,F=/(:[\w-]+\([^\)]*\))/gi,G=/(:[^\s\+>~\.\[:]+)/g,H=/([^\s\+>~\.\[:]+)/g;"undefined"!=typeof CanvasRenderingContext2D&&(CanvasRenderingContext2D.prototype.drawSvg=function(h,a,l,c,b){z(this.canvas,h,{ignoreMouse:!0,ignoreAnimation:!0,ignoreDimensions:!0,
ignoreClear:!0,offsetX:a,offsetY:l,scaleWidth:c,scaleHeight:b})});return z});
/base/000_base/node_modules/highcharts/lib/canvg.src.js
@@ -0,0 +1,3073 @@
/** @preserve
* canvg.js - Javascript SVG parser and renderer on Canvas
* MIT Licensed
* Gabe Lerner (gabelerner@gmail.com)
* http://code.google.com/p/canvg/
*
* Requires: rgbcolor.js - http://www.phpied.com/rgb-color-parser-in-javascript/
*/
(function ( global, factory ) {
 
'use strict';
 
// export as AMD...
if ( typeof define !== 'undefined' && define.amd ) {
define('canvgModule', [ 'rgbcolor', 'stackblur' ], factory );
}
 
// ...or as browserify
else if ( typeof module !== 'undefined' && module.exports ) {
module.exports = factory( require( 'rgbcolor' ), require( 'stackblur' ) );
}
 
global.canvg = factory( global.RGBColor, global.stackBlur );
 
}( typeof window !== 'undefined' ? window : this, function ( RGBColor, stackBlur ) {
// canvg(target, s)
// empty parameters: replace all 'svg' elements on page with 'canvas' elements
// target: canvas element or the id of a canvas element
// s: svg string, url to svg file, or xml document
// opts: optional hash of options
// ignoreMouse: true => ignore mouse events
// ignoreAnimation: true => ignore animations
// ignoreDimensions: true => does not try to resize canvas
// ignoreClear: true => does not clear canvas
// offsetX: int => draws at a x offset
// offsetY: int => draws at a y offset
// scaleWidth: int => scales horizontally to width
// scaleHeight: int => scales vertically to height
// renderCallback: function => will call the function after the first render is completed
// forceRedraw: function => will call the function on every frame, if it returns true, will redraw
var canvg = function (target, s, opts) {
// no parameters
if (target == null && s == null && opts == null) {
var svgTags = document.querySelectorAll('svg');
for (var i=0; i<svgTags.length; i++) {
var svgTag = svgTags[i];
var c = document.createElement('canvas');
c.width = svgTag.clientWidth;
c.height = svgTag.clientHeight;
svgTag.parentNode.insertBefore(c, svgTag);
svgTag.parentNode.removeChild(svgTag);
var div = document.createElement('div');
div.appendChild(svgTag);
canvg(c, div.innerHTML);
}
return;
}
 
if (typeof target == 'string') {
target = document.getElementById(target);
}
 
// store class on canvas
if (target.svg != null) target.svg.stop();
var svg = build(opts || {});
// on i.e. 8 for flash canvas, we can't assign the property so check for it
if (!(target.childNodes.length == 1 && target.childNodes[0].nodeName == 'OBJECT')) target.svg = svg;
 
var ctx = target.getContext('2d');
if (typeof(s.documentElement) != 'undefined') {
// load from xml doc
svg.loadXmlDoc(ctx, s);
}
else if (s.substr(0,1) == '<') {
// load from xml string
svg.loadXml(ctx, s);
}
else {
// load from url
svg.load(ctx, s);
}
}
 
// see https://developer.mozilla.org/en-US/docs/Web/API/Element.matches
var matchesSelector;
if (typeof(Element.prototype.matches) != 'undefined') {
matchesSelector = function(node, selector) {
return node.matches(selector);
};
} else if (typeof(Element.prototype.webkitMatchesSelector) != 'undefined') {
matchesSelector = function(node, selector) {
return node.webkitMatchesSelector(selector);
};
} else if (typeof(Element.prototype.mozMatchesSelector) != 'undefined') {
matchesSelector = function(node, selector) {
return node.mozMatchesSelector(selector);
};
} else if (typeof(Element.prototype.msMatchesSelector) != 'undefined') {
matchesSelector = function(node, selector) {
return node.msMatchesSelector(selector);
};
} else if (typeof(Element.prototype.oMatchesSelector) != 'undefined') {
matchesSelector = function(node, selector) {
return node.oMatchesSelector(selector);
};
} else {
// requires Sizzle: https://github.com/jquery/sizzle/wiki/Sizzle-Documentation
// or jQuery: http://jquery.com/download/
// or Zepto: http://zeptojs.com/#
// without it, this is a ReferenceError
 
if (typeof jQuery === 'function' || typeof Zepto === 'function') {
matchesSelector = function (node, selector) {
return $(node).is(selector);
};
}
 
if (typeof matchesSelector === 'undefined') {
matchesSelector = Sizzle.matchesSelector;
}
}
 
// slightly modified version of https://github.com/keeganstreet/specificity/blob/master/specificity.js
var attributeRegex = /(\[[^\]]+\])/g;
var idRegex = /(#[^\s\+>~\.\[:]+)/g;
var classRegex = /(\.[^\s\+>~\.\[:]+)/g;
var pseudoElementRegex = /(::[^\s\+>~\.\[:]+|:first-line|:first-letter|:before|:after)/gi;
var pseudoClassWithBracketsRegex = /(:[\w-]+\([^\)]*\))/gi;
var pseudoClassRegex = /(:[^\s\+>~\.\[:]+)/g;
var elementRegex = /([^\s\+>~\.\[:]+)/g;
function getSelectorSpecificity(selector) {
var typeCount = [0, 0, 0];
var findMatch = function(regex, type) {
var matches = selector.match(regex);
if (matches == null) {
return;
}
typeCount[type] += matches.length;
selector = selector.replace(regex, ' ');
};
 
selector = selector.replace(/:not\(([^\)]*)\)/g, ' $1 ');
selector = selector.replace(/{[^]*/gm, ' ');
findMatch(attributeRegex, 1);
findMatch(idRegex, 0);
findMatch(classRegex, 1);
findMatch(pseudoElementRegex, 2);
findMatch(pseudoClassWithBracketsRegex, 1);
findMatch(pseudoClassRegex, 1);
selector = selector.replace(/[\*\s\+>~]/g, ' ');
selector = selector.replace(/[#\.]/g, ' ');
findMatch(elementRegex, 2);
return typeCount.join('');
}
 
function build(opts) {
var svg = { opts: opts };
 
svg.FRAMERATE = 30;
svg.MAX_VIRTUAL_PIXELS = 30000;
 
svg.log = function(msg) {};
if (svg.opts['log'] == true && typeof(console) != 'undefined') {
svg.log = function(msg) { console.log(msg); };
};
 
// globals
svg.init = function(ctx) {
var uniqueId = 0;
svg.UniqueId = function () { uniqueId++; return 'canvg' + uniqueId; };
svg.Definitions = {};
svg.Styles = {};
svg.StylesSpecificity = {};
svg.Animations = [];
svg.Images = [];
svg.ctx = ctx;
svg.ViewPort = new (function () {
this.viewPorts = [];
this.Clear = function() { this.viewPorts = []; }
this.SetCurrent = function(width, height) { this.viewPorts.push({ width: width, height: height }); }
this.RemoveCurrent = function() { this.viewPorts.pop(); }
this.Current = function() { return this.viewPorts[this.viewPorts.length - 1]; }
this.width = function() { return this.Current().width; }
this.height = function() { return this.Current().height; }
this.ComputeSize = function(d) {
if (d != null && typeof(d) == 'number') return d;
if (d == 'x') return this.width();
if (d == 'y') return this.height();
return Math.sqrt(Math.pow(this.width(), 2) + Math.pow(this.height(), 2)) / Math.sqrt(2);
}
});
}
svg.init();
 
// images loaded
svg.ImagesLoaded = function() {
for (var i=0; i<svg.Images.length; i++) {
if (!svg.Images[i].loaded) return false;
}
return true;
}
 
// trim
svg.trim = function(s) { return s.replace(/^\s+|\s+$/g, ''); }
 
// compress spaces
svg.compressSpaces = function(s) { return s.replace(/[\s\r\t\n]+/gm,' '); }
 
// ajax
svg.ajax = function(url) {
var AJAX;
if(window.XMLHttpRequest){AJAX=new XMLHttpRequest();}
else{AJAX=new ActiveXObject('Microsoft.XMLHTTP');}
if(AJAX){
AJAX.open('GET',url,false);
AJAX.send(null);
return AJAX.responseText;
}
return null;
}
 
// parse xml
svg.parseXml = function(xml) {
if (typeof(Windows) != 'undefined' && typeof(Windows.Data) != 'undefined' && typeof(Windows.Data.Xml) != 'undefined') {
var xmlDoc = new Windows.Data.Xml.Dom.XmlDocument();
var settings = new Windows.Data.Xml.Dom.XmlLoadSettings();
settings.prohibitDtd = false;
xmlDoc.loadXml(xml, settings);
return xmlDoc;
}
else if (window.DOMParser)
{
var parser = new DOMParser();
return parser.parseFromString(xml, 'text/xml');
}
else
{
xml = xml.replace(/<!DOCTYPE svg[^>]*>/, '');
var xmlDoc = new ActiveXObject('Microsoft.XMLDOM');
xmlDoc.async = 'false';
xmlDoc.loadXML(xml);
return xmlDoc;
}
}
 
svg.Property = function(name, value) {
this.name = name;
this.value = value;
}
svg.Property.prototype.getValue = function() {
return this.value;
}
 
svg.Property.prototype.hasValue = function() {
return (this.value != null && this.value !== '');
}
 
// return the numerical value of the property
svg.Property.prototype.numValue = function() {
if (!this.hasValue()) return 0;
 
var n = parseFloat(this.value);
if ((this.value + '').match(/%$/)) {
n = n / 100.0;
}
return n;
}
 
svg.Property.prototype.valueOrDefault = function(def) {
if (this.hasValue()) return this.value;
return def;
}
 
svg.Property.prototype.numValueOrDefault = function(def) {
if (this.hasValue()) return this.numValue();
return def;
}
 
// color extensions
// augment the current color value with the opacity
svg.Property.prototype.addOpacity = function(opacityProp) {
var newValue = this.value;
if (opacityProp.value != null && opacityProp.value != '' && typeof(this.value)=='string') { // can only add opacity to colors, not patterns
var color = new RGBColor(this.value);
if (color.ok) {
newValue = 'rgba(' + color.r + ', ' + color.g + ', ' + color.b + ', ' + opacityProp.numValue() + ')';
}
}
return new svg.Property(this.name, newValue);
}
 
// definition extensions
// get the definition from the definitions table
svg.Property.prototype.getDefinition = function() {
var name = this.value.match(/#([^\)'"]+)/);
if (name) { name = name[1]; }
if (!name) { name = this.value; }
return svg.Definitions[name];
}
 
svg.Property.prototype.isUrlDefinition = function() {
return this.value.indexOf('url(') == 0
}
 
svg.Property.prototype.getFillStyleDefinition = function(e, opacityProp) {
var def = this.getDefinition();
 
// gradient
if (def != null && def.createGradient) {
return def.createGradient(svg.ctx, e, opacityProp);
}
 
// pattern
if (def != null && def.createPattern) {
if (def.getHrefAttribute().hasValue()) {
var pt = def.attribute('patternTransform');
def = def.getHrefAttribute().getDefinition();
if (pt.hasValue()) { def.attribute('patternTransform', true).value = pt.value; }
}
return def.createPattern(svg.ctx, e);
}
 
return null;
}
 
// length extensions
svg.Property.prototype.getDPI = function(viewPort) {
return 96.0; // TODO: compute?
}
 
svg.Property.prototype.getEM = function(viewPort) {
var em = 12;
 
var fontSize = new svg.Property('fontSize', svg.Font.Parse(svg.ctx.font).fontSize);
if (fontSize.hasValue()) em = fontSize.toPixels(viewPort);
 
return em;
}
 
svg.Property.prototype.getUnits = function() {
var s = this.value+'';
return s.replace(/[0-9\.\-]/g,'');
}
 
// get the length as pixels
svg.Property.prototype.toPixels = function(viewPort, processPercent) {
if (!this.hasValue()) return 0;
var s = this.value+'';
if (s.match(/em$/)) return this.numValue() * this.getEM(viewPort);
if (s.match(/ex$/)) return this.numValue() * this.getEM(viewPort) / 2.0;
if (s.match(/px$/)) return this.numValue();
if (s.match(/pt$/)) return this.numValue() * this.getDPI(viewPort) * (1.0 / 72.0);
if (s.match(/pc$/)) return this.numValue() * 15;
if (s.match(/cm$/)) return this.numValue() * this.getDPI(viewPort) / 2.54;
if (s.match(/mm$/)) return this.numValue() * this.getDPI(viewPort) / 25.4;
if (s.match(/in$/)) return this.numValue() * this.getDPI(viewPort);
if (s.match(/%$/)) return this.numValue() * svg.ViewPort.ComputeSize(viewPort);
var n = this.numValue();
if (processPercent && n < 1.0) return n * svg.ViewPort.ComputeSize(viewPort);
return n;
}
 
// time extensions
// get the time as milliseconds
svg.Property.prototype.toMilliseconds = function() {
if (!this.hasValue()) return 0;
var s = this.value+'';
if (s.match(/s$/)) return this.numValue() * 1000;
if (s.match(/ms$/)) return this.numValue();
return this.numValue();
}
 
// angle extensions
// get the angle as radians
svg.Property.prototype.toRadians = function() {
if (!this.hasValue()) return 0;
var s = this.value+'';
if (s.match(/deg$/)) return this.numValue() * (Math.PI / 180.0);
if (s.match(/grad$/)) return this.numValue() * (Math.PI / 200.0);
if (s.match(/rad$/)) return this.numValue();
return this.numValue() * (Math.PI / 180.0);
}
 
// text extensions
// get the text baseline
var textBaselineMapping = {
'baseline': 'alphabetic',
'before-edge': 'top',
'text-before-edge': 'top',
'middle': 'middle',
'central': 'middle',
'after-edge': 'bottom',
'text-after-edge': 'bottom',
'ideographic': 'ideographic',
'alphabetic': 'alphabetic',
'hanging': 'hanging',
'mathematical': 'alphabetic'
};
svg.Property.prototype.toTextBaseline = function () {
if (!this.hasValue()) return null;
return textBaselineMapping[this.value];
}
 
// fonts
svg.Font = new (function() {
this.Styles = 'normal|italic|oblique|inherit';
this.Variants = 'normal|small-caps|inherit';
this.Weights = 'normal|bold|bolder|lighter|100|200|300|400|500|600|700|800|900|inherit';
 
this.CreateFont = function(fontStyle, fontVariant, fontWeight, fontSize, fontFamily, inherit) {
var f = inherit != null ? this.Parse(inherit) : this.CreateFont('', '', '', '', '', svg.ctx.font);
return {
fontFamily: fontFamily || f.fontFamily,
fontSize: fontSize || f.fontSize,
fontStyle: fontStyle || f.fontStyle,
fontWeight: fontWeight || f.fontWeight,
fontVariant: fontVariant || f.fontVariant,
toString: function () { return [this.fontStyle, this.fontVariant, this.fontWeight, this.fontSize, this.fontFamily].join(' ') }
}
}
 
var that = this;
this.Parse = function(s) {
var f = {};
var d = svg.trim(svg.compressSpaces(s || '')).split(' ');
var set = { fontSize: false, fontStyle: false, fontWeight: false, fontVariant: false }
var ff = '';
for (var i=0; i<d.length; i++) {
if (!set.fontStyle && that.Styles.indexOf(d[i]) != -1) { if (d[i] != 'inherit') f.fontStyle = d[i]; set.fontStyle = true; }
else if (!set.fontVariant && that.Variants.indexOf(d[i]) != -1) { if (d[i] != 'inherit') f.fontVariant = d[i]; set.fontStyle = set.fontVariant = true; }
else if (!set.fontWeight && that.Weights.indexOf(d[i]) != -1) { if (d[i] != 'inherit') f.fontWeight = d[i]; set.fontStyle = set.fontVariant = set.fontWeight = true; }
else if (!set.fontSize) { if (d[i] != 'inherit') f.fontSize = d[i].split('/')[0]; set.fontStyle = set.fontVariant = set.fontWeight = set.fontSize = true; }
else { if (d[i] != 'inherit') ff += d[i]; }
} if (ff != '') f.fontFamily = ff;
return f;
}
});
 
// points and paths
svg.ToNumberArray = function(s) {
var a = svg.trim(svg.compressSpaces((s || '').replace(/,/g, ' '))).split(' ');
for (var i=0; i<a.length; i++) {
a[i] = parseFloat(a[i]);
}
return a;
}
svg.Point = function(x, y) {
this.x = x;
this.y = y;
}
svg.Point.prototype.angleTo = function(p) {
return Math.atan2(p.y - this.y, p.x - this.x);
}
 
svg.Point.prototype.applyTransform = function(v) {
var xp = this.x * v[0] + this.y * v[2] + v[4];
var yp = this.x * v[1] + this.y * v[3] + v[5];
this.x = xp;
this.y = yp;
}
 
svg.CreatePoint = function(s) {
var a = svg.ToNumberArray(s);
return new svg.Point(a[0], a[1]);
}
svg.CreatePath = function(s) {
var a = svg.ToNumberArray(s);
var path = [];
for (var i=0; i<a.length; i+=2) {
path.push(new svg.Point(a[i], a[i+1]));
}
return path;
}
 
// bounding box
svg.BoundingBox = function(x1, y1, x2, y2) { // pass in initial points if you want
this.x1 = Number.NaN;
this.y1 = Number.NaN;
this.x2 = Number.NaN;
this.y2 = Number.NaN;
 
this.x = function() { return this.x1; }
this.y = function() { return this.y1; }
this.width = function() { return this.x2 - this.x1; }
this.height = function() { return this.y2 - this.y1; }
 
this.addPoint = function(x, y) {
if (x != null) {
if (isNaN(this.x1) || isNaN(this.x2)) {
this.x1 = x;
this.x2 = x;
}
if (x < this.x1) this.x1 = x;
if (x > this.x2) this.x2 = x;
}
 
if (y != null) {
if (isNaN(this.y1) || isNaN(this.y2)) {
this.y1 = y;
this.y2 = y;
}
if (y < this.y1) this.y1 = y;
if (y > this.y2) this.y2 = y;
}
}
this.addX = function(x) { this.addPoint(x, null); }
this.addY = function(y) { this.addPoint(null, y); }
 
this.addBoundingBox = function(bb) {
this.addPoint(bb.x1, bb.y1);
this.addPoint(bb.x2, bb.y2);
}
 
this.addQuadraticCurve = function(p0x, p0y, p1x, p1y, p2x, p2y) {
var cp1x = p0x + 2/3 * (p1x - p0x); // CP1 = QP0 + 2/3 *(QP1-QP0)
var cp1y = p0y + 2/3 * (p1y - p0y); // CP1 = QP0 + 2/3 *(QP1-QP0)
var cp2x = cp1x + 1/3 * (p2x - p0x); // CP2 = CP1 + 1/3 *(QP2-QP0)
var cp2y = cp1y + 1/3 * (p2y - p0y); // CP2 = CP1 + 1/3 *(QP2-QP0)
this.addBezierCurve(p0x, p0y, cp1x, cp2x, cp1y, cp2y, p2x, p2y);
}
 
this.addBezierCurve = function(p0x, p0y, p1x, p1y, p2x, p2y, p3x, p3y) {
// from http://blog.hackers-cafe.net/2009/06/how-to-calculate-bezier-curves-bounding.html
var p0 = [p0x, p0y], p1 = [p1x, p1y], p2 = [p2x, p2y], p3 = [p3x, p3y];
this.addPoint(p0[0], p0[1]);
this.addPoint(p3[0], p3[1]);
 
for (i=0; i<=1; i++) {
var f = function(t) {
return Math.pow(1-t, 3) * p0[i]
+ 3 * Math.pow(1-t, 2) * t * p1[i]
+ 3 * (1-t) * Math.pow(t, 2) * p2[i]
+ Math.pow(t, 3) * p3[i];
}
 
var b = 6 * p0[i] - 12 * p1[i] + 6 * p2[i];
var a = -3 * p0[i] + 9 * p1[i] - 9 * p2[i] + 3 * p3[i];
var c = 3 * p1[i] - 3 * p0[i];
 
if (a == 0) {
if (b == 0) continue;
var t = -c / b;
if (0 < t && t < 1) {
if (i == 0) this.addX(f(t));
if (i == 1) this.addY(f(t));
}
continue;
}
 
var b2ac = Math.pow(b, 2) - 4 * c * a;
if (b2ac < 0) continue;
var t1 = (-b + Math.sqrt(b2ac)) / (2 * a);
if (0 < t1 && t1 < 1) {
if (i == 0) this.addX(f(t1));
if (i == 1) this.addY(f(t1));
}
var t2 = (-b - Math.sqrt(b2ac)) / (2 * a);
if (0 < t2 && t2 < 1) {
if (i == 0) this.addX(f(t2));
if (i == 1) this.addY(f(t2));
}
}
}
 
this.isPointInBox = function(x, y) {
return (this.x1 <= x && x <= this.x2 && this.y1 <= y && y <= this.y2);
}
 
this.addPoint(x1, y1);
this.addPoint(x2, y2);
}
 
// transforms
svg.Transform = function(v) {
var that = this;
this.Type = {}
 
// translate
this.Type.translate = function(s) {
this.p = svg.CreatePoint(s);
this.apply = function(ctx) {
ctx.translate(this.p.x || 0.0, this.p.y || 0.0);
}
this.unapply = function(ctx) {
ctx.translate(-1.0 * this.p.x || 0.0, -1.0 * this.p.y || 0.0);
}
this.applyToPoint = function(p) {
p.applyTransform([1, 0, 0, 1, this.p.x || 0.0, this.p.y || 0.0]);
}
}
 
// rotate
this.Type.rotate = function(s) {
var a = svg.ToNumberArray(s);
this.angle = new svg.Property('angle', a[0]);
this.cx = a[1] || 0;
this.cy = a[2] || 0;
this.apply = function(ctx) {
ctx.translate(this.cx, this.cy);
ctx.rotate(this.angle.toRadians());
ctx.translate(-this.cx, -this.cy);
}
this.unapply = function(ctx) {
ctx.translate(this.cx, this.cy);
ctx.rotate(-1.0 * this.angle.toRadians());
ctx.translate(-this.cx, -this.cy);
}
this.applyToPoint = function(p) {
var a = this.angle.toRadians();
p.applyTransform([1, 0, 0, 1, this.p.x || 0.0, this.p.y || 0.0]);
p.applyTransform([Math.cos(a), Math.sin(a), -Math.sin(a), Math.cos(a), 0, 0]);
p.applyTransform([1, 0, 0, 1, -this.p.x || 0.0, -this.p.y || 0.0]);
}
}
 
this.Type.scale = function(s) {
this.p = svg.CreatePoint(s);
this.apply = function(ctx) {
ctx.scale(this.p.x || 1.0, this.p.y || this.p.x || 1.0);
}
this.unapply = function(ctx) {
ctx.scale(1.0 / this.p.x || 1.0, 1.0 / this.p.y || this.p.x || 1.0);
}
this.applyToPoint = function(p) {
p.applyTransform([this.p.x || 0.0, 0, 0, this.p.y || 0.0, 0, 0]);
}
}
 
this.Type.matrix = function(s) {
this.m = svg.ToNumberArray(s);
this.apply = function(ctx) {
ctx.transform(this.m[0], this.m[1], this.m[2], this.m[3], this.m[4], this.m[5]);
}
this.unapply = function(ctx) {
var a = this.m[0];
var b = this.m[2];
var c = this.m[4];
var d = this.m[1];
var e = this.m[3];
var f = this.m[5];
var g = 0.0;
var h = 0.0;
var i = 1.0;
var det = 1 / (a*(e*i-f*h)-b*(d*i-f*g)+c*(d*h-e*g));
ctx.transform(
det*(e*i-f*h),
det*(f*g-d*i),
det*(c*h-b*i),
det*(a*i-c*g),
det*(b*f-c*e),
det*(c*d-a*f)
);
}
this.applyToPoint = function(p) {
p.applyTransform(this.m);
}
}
 
this.Type.SkewBase = function(s) {
this.base = that.Type.matrix;
this.base(s);
this.angle = new svg.Property('angle', s);
}
this.Type.SkewBase.prototype = new this.Type.matrix;
 
this.Type.skewX = function(s) {
this.base = that.Type.SkewBase;
this.base(s);
this.m = [1, 0, Math.tan(this.angle.toRadians()), 1, 0, 0];
}
this.Type.skewX.prototype = new this.Type.SkewBase;
 
this.Type.skewY = function(s) {
this.base = that.Type.SkewBase;
this.base(s);
this.m = [1, Math.tan(this.angle.toRadians()), 0, 1, 0, 0];
}
this.Type.skewY.prototype = new this.Type.SkewBase;
 
this.transforms = [];
 
this.apply = function(ctx) {
for (var i=0; i<this.transforms.length; i++) {
this.transforms[i].apply(ctx);
}
}
 
this.unapply = function(ctx) {
for (var i=this.transforms.length-1; i>=0; i--) {
this.transforms[i].unapply(ctx);
}
}
 
this.applyToPoint = function(p) {
for (var i=0; i<this.transforms.length; i++) {
this.transforms[i].applyToPoint(p);
}
}
 
var data = svg.trim(svg.compressSpaces(v)).replace(/\)([a-zA-Z])/g, ') $1').replace(/\)(\s?,\s?)/g,') ').split(/\s(?=[a-z])/);
for (var i=0; i<data.length; i++) {
var type = svg.trim(data[i].split('(')[0]);
var s = data[i].split('(')[1].replace(')','');
var transform = new this.Type[type](s);
transform.type = type;
this.transforms.push(transform);
}
}
 
// aspect ratio
svg.AspectRatio = function(ctx, aspectRatio, width, desiredWidth, height, desiredHeight, minX, minY, refX, refY) {
// aspect ratio - http://www.w3.org/TR/SVG/coords.html#PreserveAspectRatioAttribute
aspectRatio = svg.compressSpaces(aspectRatio);
aspectRatio = aspectRatio.replace(/^defer\s/,''); // ignore defer
var align = aspectRatio.split(' ')[0] || 'xMidYMid';
var meetOrSlice = aspectRatio.split(' ')[1] || 'meet';
 
// calculate scale
var scaleX = width / desiredWidth;
var scaleY = height / desiredHeight;
var scaleMin = Math.min(scaleX, scaleY);
var scaleMax = Math.max(scaleX, scaleY);
if (meetOrSlice == 'meet') { desiredWidth *= scaleMin; desiredHeight *= scaleMin; }
if (meetOrSlice == 'slice') { desiredWidth *= scaleMax; desiredHeight *= scaleMax; }
 
refX = new svg.Property('refX', refX);
refY = new svg.Property('refY', refY);
if (refX.hasValue() && refY.hasValue()) {
ctx.translate(-scaleMin * refX.toPixels('x'), -scaleMin * refY.toPixels('y'));
}
else {
// align
if (align.match(/^xMid/) && ((meetOrSlice == 'meet' && scaleMin == scaleY) || (meetOrSlice == 'slice' && scaleMax == scaleY))) ctx.translate(width / 2.0 - desiredWidth / 2.0, 0);
if (align.match(/YMid$/) && ((meetOrSlice == 'meet' && scaleMin == scaleX) || (meetOrSlice == 'slice' && scaleMax == scaleX))) ctx.translate(0, height / 2.0 - desiredHeight / 2.0);
if (align.match(/^xMax/) && ((meetOrSlice == 'meet' && scaleMin == scaleY) || (meetOrSlice == 'slice' && scaleMax == scaleY))) ctx.translate(width - desiredWidth, 0);
if (align.match(/YMax$/) && ((meetOrSlice == 'meet' && scaleMin == scaleX) || (meetOrSlice == 'slice' && scaleMax == scaleX))) ctx.translate(0, height - desiredHeight);
}
 
// scale
if (align == 'none') ctx.scale(scaleX, scaleY);
else if (meetOrSlice == 'meet') ctx.scale(scaleMin, scaleMin);
else if (meetOrSlice == 'slice') ctx.scale(scaleMax, scaleMax);
 
// translate
ctx.translate(minX == null ? 0 : -minX, minY == null ? 0 : -minY);
}
 
// elements
svg.Element = {}
 
svg.EmptyProperty = new svg.Property('EMPTY', '');
 
svg.Element.ElementBase = function(node) {
this.attributes = {};
this.styles = {};
this.stylesSpecificity = {};
this.children = [];
 
// get or create attribute
this.attribute = function(name, createIfNotExists) {
var a = this.attributes[name];
if (a != null) return a;
 
if (createIfNotExists == true) { a = new svg.Property(name, ''); this.attributes[name] = a; }
return a || svg.EmptyProperty;
}
 
this.getHrefAttribute = function() {
for (var a in this.attributes) {
if (a == 'href' || a.match(/:href$/)) {
return this.attributes[a];
}
}
return svg.EmptyProperty;
}
 
// get or create style, crawls up node tree
this.style = function(name, createIfNotExists, skipAncestors) {
var s = this.styles[name];
if (s != null) return s;
 
var a = this.attribute(name);
if (a != null && a.hasValue()) {
this.styles[name] = a; // move up to me to cache
return a;
}
 
if (skipAncestors != true) {
var p = this.parent;
if (p != null) {
var ps = p.style(name);
if (ps != null && ps.hasValue()) {
return ps;
}
}
}
 
if (createIfNotExists == true) { s = new svg.Property(name, ''); this.styles[name] = s; }
return s || svg.EmptyProperty;
}
 
// base render
this.render = function(ctx) {
// don't render display=none
if (this.style('display').value == 'none') return;
 
// don't render visibility=hidden
if (this.style('visibility').value == 'hidden') return;
 
ctx.save();
if (this.style('mask').hasValue()) { // mask
var mask = this.style('mask').getDefinition();
if (mask != null) mask.apply(ctx, this);
}
else if (this.style('filter').hasValue()) { // filter
var filter = this.style('filter').getDefinition();
if (filter != null) filter.apply(ctx, this);
}
else {
this.setContext(ctx);
this.renderChildren(ctx);
this.clearContext(ctx);
}
ctx.restore();
}
 
// base set context
this.setContext = function(ctx) {
// OVERRIDE ME!
}
 
// base clear context
this.clearContext = function(ctx) {
// OVERRIDE ME!
}
 
// base render children
this.renderChildren = function(ctx) {
for (var i=0; i<this.children.length; i++) {
this.children[i].render(ctx);
}
}
 
this.addChild = function(childNode, create) {
var child = childNode;
if (create) child = svg.CreateElement(childNode);
child.parent = this;
if (child.type != 'title') { this.children.push(child); }
}
this.addStylesFromStyleDefinition = function () {
// add styles
for (var selector in svg.Styles) {
if (selector[0] != '@' && matchesSelector(node, selector)) {
var styles = svg.Styles[selector];
var specificity = svg.StylesSpecificity[selector];
if (styles != null) {
for (var name in styles) {
var existingSpecificity = this.stylesSpecificity[name];
if (typeof(existingSpecificity) == 'undefined') {
existingSpecificity = '000';
}
if (specificity > existingSpecificity) {
this.styles[name] = styles[name];
this.stylesSpecificity[name] = specificity;
}
}
}
}
}
};
 
if (node != null && node.nodeType == 1) { //ELEMENT_NODE
// add attributes
for (var i=0; i<node.attributes.length; i++) {
var attribute = node.attributes[i];
this.attributes[attribute.nodeName] = new svg.Property(attribute.nodeName, attribute.value);
}
this.addStylesFromStyleDefinition();
 
// add inline styles
if (this.attribute('style').hasValue()) {
var styles = this.attribute('style').value.split(';');
for (var i=0; i<styles.length; i++) {
if (svg.trim(styles[i]) != '') {
var style = styles[i].split(':');
var name = svg.trim(style[0]);
var value = svg.trim(style[1]);
this.styles[name] = new svg.Property(name, value);
}
}
}
 
// add id
if (this.attribute('id').hasValue()) {
if (svg.Definitions[this.attribute('id').value] == null) {
svg.Definitions[this.attribute('id').value] = this;
}
}
 
// add children
for (var i=0; i<node.childNodes.length; i++) {
var childNode = node.childNodes[i];
if (childNode.nodeType == 1) this.addChild(childNode, true); //ELEMENT_NODE
if (this.captureTextNodes && (childNode.nodeType == 3 || childNode.nodeType == 4)) {
var text = childNode.value || childNode.text || childNode.textContent || '';
if (svg.compressSpaces(text) != '') {
this.addChild(new svg.Element.tspan(childNode), false); // TEXT_NODE
}
}
}
}
}
 
svg.Element.RenderedElementBase = function(node) {
this.base = svg.Element.ElementBase;
this.base(node);
 
this.setContext = function(ctx) {
// fill
if (this.style('fill').isUrlDefinition()) {
var fs = this.style('fill').getFillStyleDefinition(this, this.style('fill-opacity'));
if (fs != null) ctx.fillStyle = fs;
}
else if (this.style('fill').hasValue()) {
var fillStyle = this.style('fill');
if (fillStyle.value == 'currentColor') fillStyle.value = this.style('color').value;
if (fillStyle.value != 'inherit') ctx.fillStyle = (fillStyle.value == 'none' ? 'rgba(0,0,0,0)' : fillStyle.value);
}
if (this.style('fill-opacity').hasValue()) {
var fillStyle = new svg.Property('fill', ctx.fillStyle);
fillStyle = fillStyle.addOpacity(this.style('fill-opacity'));
ctx.fillStyle = fillStyle.value;
}
 
// stroke
if (this.style('stroke').isUrlDefinition()) {
var fs = this.style('stroke').getFillStyleDefinition(this, this.style('stroke-opacity'));
if (fs != null) ctx.strokeStyle = fs;
}
else if (this.style('stroke').hasValue()) {
var strokeStyle = this.style('stroke');
if (strokeStyle.value == 'currentColor') strokeStyle.value = this.style('color').value;
if (strokeStyle.value != 'inherit') ctx.strokeStyle = (strokeStyle.value == 'none' ? 'rgba(0,0,0,0)' : strokeStyle.value);
}
if (this.style('stroke-opacity').hasValue()) {
var strokeStyle = new svg.Property('stroke', ctx.strokeStyle);
strokeStyle = strokeStyle.addOpacity(this.style('stroke-opacity'));
ctx.strokeStyle = strokeStyle.value;
}
if (this.style('stroke-width').hasValue()) {
var newLineWidth = this.style('stroke-width').toPixels();
ctx.lineWidth = newLineWidth == 0 ? 0.001 : newLineWidth; // browsers don't respect 0
}
if (this.style('stroke-linecap').hasValue()) ctx.lineCap = this.style('stroke-linecap').value;
if (this.style('stroke-linejoin').hasValue()) ctx.lineJoin = this.style('stroke-linejoin').value;
if (this.style('stroke-miterlimit').hasValue()) ctx.miterLimit = this.style('stroke-miterlimit').value;
if (this.style('stroke-dasharray').hasValue() && this.style('stroke-dasharray').value != 'none') {
var gaps = svg.ToNumberArray(this.style('stroke-dasharray').value);
if (typeof(ctx.setLineDash) != 'undefined') { ctx.setLineDash(gaps); }
else if (typeof(ctx.webkitLineDash) != 'undefined') { ctx.webkitLineDash = gaps; }
else if (typeof(ctx.mozDash) != 'undefined' && !(gaps.length==1 && gaps[0]==0)) { ctx.mozDash = gaps; }
 
var offset = this.style('stroke-dashoffset').numValueOrDefault(1);
if (typeof(ctx.lineDashOffset) != 'undefined') { ctx.lineDashOffset = offset; }
else if (typeof(ctx.webkitLineDashOffset) != 'undefined') { ctx.webkitLineDashOffset = offset; }
else if (typeof(ctx.mozDashOffset) != 'undefined') { ctx.mozDashOffset = offset; }
}
 
// font
if (typeof(ctx.font) != 'undefined') {
ctx.font = svg.Font.CreateFont(
this.style('font-style').value,
this.style('font-variant').value,
this.style('font-weight').value,
this.style('font-size').hasValue() ? this.style('font-size').toPixels() + 'px' : '',
this.style('font-family').value).toString();
}
 
// transform
if (this.style('transform', false, true).hasValue()) {
var transform = new svg.Transform(this.style('transform', false, true).value);
transform.apply(ctx);
}
 
// clip
if (this.style('clip-path', false, true).hasValue()) {
var clip = this.style('clip-path', false, true).getDefinition();
if (clip != null) clip.apply(ctx);
}
 
// opacity
if (this.style('opacity').hasValue()) {
ctx.globalAlpha = this.style('opacity').numValue();
}
}
}
svg.Element.RenderedElementBase.prototype = new svg.Element.ElementBase;
 
svg.Element.PathElementBase = function(node) {
this.base = svg.Element.RenderedElementBase;
this.base(node);
 
this.path = function(ctx) {
if (ctx != null) ctx.beginPath();
return new svg.BoundingBox();
}
 
this.renderChildren = function(ctx) {
this.path(ctx);
svg.Mouse.checkPath(this, ctx);
if (ctx.fillStyle != '') {
if (this.style('fill-rule').valueOrDefault('inherit') != 'inherit') { ctx.fill(this.style('fill-rule').value); }
else { ctx.fill(); }
}
if (ctx.strokeStyle != '') ctx.stroke();
 
var markers = this.getMarkers();
if (markers != null) {
if (this.style('marker-start').isUrlDefinition()) {
var marker = this.style('marker-start').getDefinition();
marker.render(ctx, markers[0][0], markers[0][1]);
}
if (this.style('marker-mid').isUrlDefinition()) {
var marker = this.style('marker-mid').getDefinition();
for (var i=1;i<markers.length-1;i++) {
marker.render(ctx, markers[i][0], markers[i][1]);
}
}
if (this.style('marker-end').isUrlDefinition()) {
var marker = this.style('marker-end').getDefinition();
marker.render(ctx, markers[markers.length-1][0], markers[markers.length-1][1]);
}
}
}
 
this.getBoundingBox = function() {
return this.path();
}
 
this.getMarkers = function() {
return null;
}
}
svg.Element.PathElementBase.prototype = new svg.Element.RenderedElementBase;
 
// svg element
svg.Element.svg = function(node) {
this.base = svg.Element.RenderedElementBase;
this.base(node);
 
this.baseClearContext = this.clearContext;
this.clearContext = function(ctx) {
this.baseClearContext(ctx);
svg.ViewPort.RemoveCurrent();
}
 
this.baseSetContext = this.setContext;
this.setContext = function(ctx) {
// initial values and defaults
ctx.strokeStyle = 'rgba(0,0,0,0)';
ctx.lineCap = 'butt';
ctx.lineJoin = 'miter';
ctx.miterLimit = 4;
if (typeof(ctx.font) != 'undefined' && typeof(window.getComputedStyle) != 'undefined') {
ctx.font = window.getComputedStyle(ctx.canvas).getPropertyValue('font');
}
 
this.baseSetContext(ctx);
 
// create new view port
if (!this.attribute('x').hasValue()) this.attribute('x', true).value = 0;
if (!this.attribute('y').hasValue()) this.attribute('y', true).value = 0;
ctx.translate(this.attribute('x').toPixels('x'), this.attribute('y').toPixels('y'));
 
var width = svg.ViewPort.width();
var height = svg.ViewPort.height();
 
if (!this.attribute('width').hasValue()) this.attribute('width', true).value = '100%';
if (!this.attribute('height').hasValue()) this.attribute('height', true).value = '100%';
if (typeof(this.root) == 'undefined') {
width = this.attribute('width').toPixels('x');
height = this.attribute('height').toPixels('y');
 
var x = 0;
var y = 0;
if (this.attribute('refX').hasValue() && this.attribute('refY').hasValue()) {
x = -this.attribute('refX').toPixels('x');
y = -this.attribute('refY').toPixels('y');
}
 
if (this.attribute('overflow').valueOrDefault('hidden') != 'visible') {
ctx.beginPath();
ctx.moveTo(x, y);
ctx.lineTo(width, y);
ctx.lineTo(width, height);
ctx.lineTo(x, height);
ctx.closePath();
ctx.clip();
}
}
svg.ViewPort.SetCurrent(width, height);
 
// viewbox
if (this.attribute('viewBox').hasValue()) {
var viewBox = svg.ToNumberArray(this.attribute('viewBox').value);
var minX = viewBox[0];
var minY = viewBox[1];
width = viewBox[2];
height = viewBox[3];
 
svg.AspectRatio(ctx,
this.attribute('preserveAspectRatio').value,
svg.ViewPort.width(),
width,
svg.ViewPort.height(),
height,
minX,
minY,
this.attribute('refX').value,
this.attribute('refY').value);
 
svg.ViewPort.RemoveCurrent();
svg.ViewPort.SetCurrent(viewBox[2], viewBox[3]);
}
}
}
svg.Element.svg.prototype = new svg.Element.RenderedElementBase;
 
// rect element
svg.Element.rect = function(node) {
this.base = svg.Element.PathElementBase;
this.base(node);
 
this.path = function(ctx) {
var x = this.attribute('x').toPixels('x');
var y = this.attribute('y').toPixels('y');
var width = this.attribute('width').toPixels('x');
var height = this.attribute('height').toPixels('y');
var rx = this.attribute('rx').toPixels('x');
var ry = this.attribute('ry').toPixels('y');
if (this.attribute('rx').hasValue() && !this.attribute('ry').hasValue()) ry = rx;
if (this.attribute('ry').hasValue() && !this.attribute('rx').hasValue()) rx = ry;
rx = Math.min(rx, width / 2.0);
ry = Math.min(ry, height / 2.0);
if (ctx != null) {
ctx.beginPath();
ctx.moveTo(x + rx, y);
ctx.lineTo(x + width - rx, y);
ctx.quadraticCurveTo(x + width, y, x + width, y + ry)
ctx.lineTo(x + width, y + height - ry);
ctx.quadraticCurveTo(x + width, y + height, x + width - rx, y + height)
ctx.lineTo(x + rx, y + height);
ctx.quadraticCurveTo(x, y + height, x, y + height - ry)
ctx.lineTo(x, y + ry);
ctx.quadraticCurveTo(x, y, x + rx, y)
ctx.closePath();
}
 
return new svg.BoundingBox(x, y, x + width, y + height);
}
}
svg.Element.rect.prototype = new svg.Element.PathElementBase;
 
// circle element
svg.Element.circle = function(node) {
this.base = svg.Element.PathElementBase;
this.base(node);
 
this.path = function(ctx) {
var cx = this.attribute('cx').toPixels('x');
var cy = this.attribute('cy').toPixels('y');
var r = this.attribute('r').toPixels();
 
if (ctx != null) {
ctx.beginPath();
ctx.arc(cx, cy, r, 0, Math.PI * 2, true);
ctx.closePath();
}
 
return new svg.BoundingBox(cx - r, cy - r, cx + r, cy + r);
}
}
svg.Element.circle.prototype = new svg.Element.PathElementBase;
 
// ellipse element
svg.Element.ellipse = function(node) {
this.base = svg.Element.PathElementBase;
this.base(node);
 
this.path = function(ctx) {
var KAPPA = 4 * ((Math.sqrt(2) - 1) / 3);
var rx = this.attribute('rx').toPixels('x');
var ry = this.attribute('ry').toPixels('y');
var cx = this.attribute('cx').toPixels('x');
var cy = this.attribute('cy').toPixels('y');
 
if (ctx != null) {
ctx.beginPath();
ctx.moveTo(cx, cy - ry);
ctx.bezierCurveTo(cx + (KAPPA * rx), cy - ry, cx + rx, cy - (KAPPA * ry), cx + rx, cy);
ctx.bezierCurveTo(cx + rx, cy + (KAPPA * ry), cx + (KAPPA * rx), cy + ry, cx, cy + ry);
ctx.bezierCurveTo(cx - (KAPPA * rx), cy + ry, cx - rx, cy + (KAPPA * ry), cx - rx, cy);
ctx.bezierCurveTo(cx - rx, cy - (KAPPA * ry), cx - (KAPPA * rx), cy - ry, cx, cy - ry);
ctx.closePath();
}
 
return new svg.BoundingBox(cx - rx, cy - ry, cx + rx, cy + ry);
}
}
svg.Element.ellipse.prototype = new svg.Element.PathElementBase;
 
// line element
svg.Element.line = function(node) {
this.base = svg.Element.PathElementBase;
this.base(node);
 
this.getPoints = function() {
return [
new svg.Point(this.attribute('x1').toPixels('x'), this.attribute('y1').toPixels('y')),
new svg.Point(this.attribute('x2').toPixels('x'), this.attribute('y2').toPixels('y'))];
}
 
this.path = function(ctx) {
var points = this.getPoints();
 
if (ctx != null) {
ctx.beginPath();
ctx.moveTo(points[0].x, points[0].y);
ctx.lineTo(points[1].x, points[1].y);
}
 
return new svg.BoundingBox(points[0].x, points[0].y, points[1].x, points[1].y);
}
 
this.getMarkers = function() {
var points = this.getPoints();
var a = points[0].angleTo(points[1]);
return [[points[0], a], [points[1], a]];
}
}
svg.Element.line.prototype = new svg.Element.PathElementBase;
 
// polyline element
svg.Element.polyline = function(node) {
this.base = svg.Element.PathElementBase;
this.base(node);
 
this.points = svg.CreatePath(this.attribute('points').value);
this.path = function(ctx) {
var bb = new svg.BoundingBox(this.points[0].x, this.points[0].y);
if (ctx != null) {
ctx.beginPath();
ctx.moveTo(this.points[0].x, this.points[0].y);
}
for (var i=1; i<this.points.length; i++) {
bb.addPoint(this.points[i].x, this.points[i].y);
if (ctx != null) ctx.lineTo(this.points[i].x, this.points[i].y);
}
return bb;
}
 
this.getMarkers = function() {
var markers = [];
for (var i=0; i<this.points.length - 1; i++) {
markers.push([this.points[i], this.points[i].angleTo(this.points[i+1])]);
}
markers.push([this.points[this.points.length-1], markers[markers.length-1][1]]);
return markers;
}
}
svg.Element.polyline.prototype = new svg.Element.PathElementBase;
 
// polygon element
svg.Element.polygon = function(node) {
this.base = svg.Element.polyline;
this.base(node);
 
this.basePath = this.path;
this.path = function(ctx) {
var bb = this.basePath(ctx);
if (ctx != null) {
ctx.lineTo(this.points[0].x, this.points[0].y);
ctx.closePath();
}
return bb;
}
}
svg.Element.polygon.prototype = new svg.Element.polyline;
 
// path element
svg.Element.path = function(node) {
this.base = svg.Element.PathElementBase;
this.base(node);
 
var d = this.attribute('d').value;
// TODO: convert to real lexer based on http://www.w3.org/TR/SVG11/paths.html#PathDataBNF
d = d.replace(/,/gm,' '); // get rid of all commas
// As the end of a match can also be the start of the next match, we need to run this replace twice.
for(var i=0; i<2; i++)
d = d.replace(/([MmZzLlHhVvCcSsQqTtAa])([^\s])/gm,'$1 $2'); // suffix commands with spaces
d = d.replace(/([^\s])([MmZzLlHhVvCcSsQqTtAa])/gm,'$1 $2'); // prefix commands with spaces
d = d.replace(/([0-9])([+\-])/gm,'$1 $2'); // separate digits on +- signs
// Again, we need to run this twice to find all occurances
for(var i=0; i<2; i++)
d = d.replace(/(\.[0-9]*)(\.)/gm,'$1 $2'); // separate digits when they start with a comma
d = d.replace(/([Aa](\s+[0-9]+){3})\s+([01])\s*([01])/gm,'$1 $3 $4 '); // shorthand elliptical arc path syntax
d = svg.compressSpaces(d); // compress multiple spaces
d = svg.trim(d);
this.PathParser = new (function(d) {
this.tokens = d.split(' ');
 
this.reset = function() {
this.i = -1;
this.command = '';
this.previousCommand = '';
this.start = new svg.Point(0, 0);
this.control = new svg.Point(0, 0);
this.current = new svg.Point(0, 0);
this.points = [];
this.angles = [];
}
 
this.isEnd = function() {
return this.i >= this.tokens.length - 1;
}
 
this.isCommandOrEnd = function() {
if (this.isEnd()) return true;
return this.tokens[this.i + 1].match(/^[A-Za-z]$/) != null;
}
 
this.isRelativeCommand = function() {
switch(this.command)
{
case 'm':
case 'l':
case 'h':
case 'v':
case 'c':
case 's':
case 'q':
case 't':
case 'a':
case 'z':
return true;
break;
}
return false;
}
 
this.getToken = function() {
this.i++;
return this.tokens[this.i];
}
 
this.getScalar = function() {
return parseFloat(this.getToken());
}
 
this.nextCommand = function() {
this.previousCommand = this.command;
this.command = this.getToken();
}
 
this.getPoint = function() {
var p = new svg.Point(this.getScalar(), this.getScalar());
return this.makeAbsolute(p);
}
 
this.getAsControlPoint = function() {
var p = this.getPoint();
this.control = p;
return p;
}
 
this.getAsCurrentPoint = function() {
var p = this.getPoint();
this.current = p;
return p;
}
 
this.getReflectedControlPoint = function() {
if (this.previousCommand.toLowerCase() != 'c' &&
this.previousCommand.toLowerCase() != 's' &&
this.previousCommand.toLowerCase() != 'q' &&
this.previousCommand.toLowerCase() != 't' ){
return this.current;
}
 
// reflect point
var p = new svg.Point(2 * this.current.x - this.control.x, 2 * this.current.y - this.control.y);
return p;
}
 
this.makeAbsolute = function(p) {
if (this.isRelativeCommand()) {
p.x += this.current.x;
p.y += this.current.y;
}
return p;
}
 
this.addMarker = function(p, from, priorTo) {
// if the last angle isn't filled in because we didn't have this point yet ...
if (priorTo != null && this.angles.length > 0 && this.angles[this.angles.length-1] == null) {
this.angles[this.angles.length-1] = this.points[this.points.length-1].angleTo(priorTo);
}
this.addMarkerAngle(p, from == null ? null : from.angleTo(p));
}
 
this.addMarkerAngle = function(p, a) {
this.points.push(p);
this.angles.push(a);
}
 
this.getMarkerPoints = function() { return this.points; }
this.getMarkerAngles = function() {
for (var i=0; i<this.angles.length; i++) {
if (this.angles[i] == null) {
for (var j=i+1; j<this.angles.length; j++) {
if (this.angles[j] != null) {
this.angles[i] = this.angles[j];
break;
}
}
}
}
return this.angles;
}
})(d);
 
this.path = function(ctx) {
var pp = this.PathParser;
pp.reset();
 
var bb = new svg.BoundingBox();
if (ctx != null) ctx.beginPath();
while (!pp.isEnd()) {
pp.nextCommand();
switch (pp.command) {
case 'M':
case 'm':
var p = pp.getAsCurrentPoint();
pp.addMarker(p);
bb.addPoint(p.x, p.y);
if (ctx != null) ctx.moveTo(p.x, p.y);
pp.start = pp.current;
while (!pp.isCommandOrEnd()) {
var p = pp.getAsCurrentPoint();
pp.addMarker(p, pp.start);
bb.addPoint(p.x, p.y);
if (ctx != null) ctx.lineTo(p.x, p.y);
}
break;
case 'L':
case 'l':
while (!pp.isCommandOrEnd()) {
var c = pp.current;
var p = pp.getAsCurrentPoint();
pp.addMarker(p, c);
bb.addPoint(p.x, p.y);
if (ctx != null) ctx.lineTo(p.x, p.y);
}
break;
case 'H':
case 'h':
while (!pp.isCommandOrEnd()) {
var newP = new svg.Point((pp.isRelativeCommand() ? pp.current.x : 0) + pp.getScalar(), pp.current.y);
pp.addMarker(newP, pp.current);
pp.current = newP;
bb.addPoint(pp.current.x, pp.current.y);
if (ctx != null) ctx.lineTo(pp.current.x, pp.current.y);
}
break;
case 'V':
case 'v':
while (!pp.isCommandOrEnd()) {
var newP = new svg.Point(pp.current.x, (pp.isRelativeCommand() ? pp.current.y : 0) + pp.getScalar());
pp.addMarker(newP, pp.current);
pp.current = newP;
bb.addPoint(pp.current.x, pp.current.y);
if (ctx != null) ctx.lineTo(pp.current.x, pp.current.y);
}
break;
case 'C':
case 'c':
while (!pp.isCommandOrEnd()) {
var curr = pp.current;
var p1 = pp.getPoint();
var cntrl = pp.getAsControlPoint();
var cp = pp.getAsCurrentPoint();
pp.addMarker(cp, cntrl, p1);
bb.addBezierCurve(curr.x, curr.y, p1.x, p1.y, cntrl.x, cntrl.y, cp.x, cp.y);
if (ctx != null) ctx.bezierCurveTo(p1.x, p1.y, cntrl.x, cntrl.y, cp.x, cp.y);
}
break;
case 'S':
case 's':
while (!pp.isCommandOrEnd()) {
var curr = pp.current;
var p1 = pp.getReflectedControlPoint();
var cntrl = pp.getAsControlPoint();
var cp = pp.getAsCurrentPoint();
pp.addMarker(cp, cntrl, p1);
bb.addBezierCurve(curr.x, curr.y, p1.x, p1.y, cntrl.x, cntrl.y, cp.x, cp.y);
if (ctx != null) ctx.bezierCurveTo(p1.x, p1.y, cntrl.x, cntrl.y, cp.x, cp.y);
}
break;
case 'Q':
case 'q':
while (!pp.isCommandOrEnd()) {
var curr = pp.current;
var cntrl = pp.getAsControlPoint();
var cp = pp.getAsCurrentPoint();
pp.addMarker(cp, cntrl, cntrl);
bb.addQuadraticCurve(curr.x, curr.y, cntrl.x, cntrl.y, cp.x, cp.y);
if (ctx != null) ctx.quadraticCurveTo(cntrl.x, cntrl.y, cp.x, cp.y);
}
break;
case 'T':
case 't':
while (!pp.isCommandOrEnd()) {
var curr = pp.current;
var cntrl = pp.getReflectedControlPoint();
pp.control = cntrl;
var cp = pp.getAsCurrentPoint();
pp.addMarker(cp, cntrl, cntrl);
bb.addQuadraticCurve(curr.x, curr.y, cntrl.x, cntrl.y, cp.x, cp.y);
if (ctx != null) ctx.quadraticCurveTo(cntrl.x, cntrl.y, cp.x, cp.y);
}
break;
case 'A':
case 'a':
while (!pp.isCommandOrEnd()) {
var curr = pp.current;
var rx = pp.getScalar();
var ry = pp.getScalar();
var xAxisRotation = pp.getScalar() * (Math.PI / 180.0);
var largeArcFlag = pp.getScalar();
var sweepFlag = pp.getScalar();
var cp = pp.getAsCurrentPoint();
 
// Conversion from endpoint to center parameterization
// http://www.w3.org/TR/SVG11/implnote.html#ArcImplementationNotes
// x1', y1'
var currp = new svg.Point(
Math.cos(xAxisRotation) * (curr.x - cp.x) / 2.0 + Math.sin(xAxisRotation) * (curr.y - cp.y) / 2.0,
-Math.sin(xAxisRotation) * (curr.x - cp.x) / 2.0 + Math.cos(xAxisRotation) * (curr.y - cp.y) / 2.0
);
// adjust radii
var l = Math.pow(currp.x,2)/Math.pow(rx,2)+Math.pow(currp.y,2)/Math.pow(ry,2);
if (l > 1) {
rx *= Math.sqrt(l);
ry *= Math.sqrt(l);
}
// cx', cy'
var s = (largeArcFlag == sweepFlag ? -1 : 1) * Math.sqrt(
((Math.pow(rx,2)*Math.pow(ry,2))-(Math.pow(rx,2)*Math.pow(currp.y,2))-(Math.pow(ry,2)*Math.pow(currp.x,2))) /
(Math.pow(rx,2)*Math.pow(currp.y,2)+Math.pow(ry,2)*Math.pow(currp.x,2))
);
if (isNaN(s)) s = 0;
var cpp = new svg.Point(s * rx * currp.y / ry, s * -ry * currp.x / rx);
// cx, cy
var centp = new svg.Point(
(curr.x + cp.x) / 2.0 + Math.cos(xAxisRotation) * cpp.x - Math.sin(xAxisRotation) * cpp.y,
(curr.y + cp.y) / 2.0 + Math.sin(xAxisRotation) * cpp.x + Math.cos(xAxisRotation) * cpp.y
);
// vector magnitude
var m = function(v) { return Math.sqrt(Math.pow(v[0],2) + Math.pow(v[1],2)); }
// ratio between two vectors
var r = function(u, v) { return (u[0]*v[0]+u[1]*v[1]) / (m(u)*m(v)) }
// angle between two vectors
var a = function(u, v) { return (u[0]*v[1] < u[1]*v[0] ? -1 : 1) * Math.acos(r(u,v)); }
// initial angle
var a1 = a([1,0], [(currp.x-cpp.x)/rx,(currp.y-cpp.y)/ry]);
// angle delta
var u = [(currp.x-cpp.x)/rx,(currp.y-cpp.y)/ry];
var v = [(-currp.x-cpp.x)/rx,(-currp.y-cpp.y)/ry];
var ad = a(u, v);
if (r(u,v) <= -1) ad = Math.PI;
if (r(u,v) >= 1) ad = 0;
 
// for markers
var dir = 1 - sweepFlag ? 1.0 : -1.0;
var ah = a1 + dir * (ad / 2.0);
var halfWay = new svg.Point(
centp.x + rx * Math.cos(ah),
centp.y + ry * Math.sin(ah)
);
pp.addMarkerAngle(halfWay, ah - dir * Math.PI / 2);
pp.addMarkerAngle(cp, ah - dir * Math.PI);
 
bb.addPoint(cp.x, cp.y); // TODO: this is too naive, make it better
if (ctx != null) {
var r = rx > ry ? rx : ry;
var sx = rx > ry ? 1 : rx / ry;
var sy = rx > ry ? ry / rx : 1;
 
ctx.translate(centp.x, centp.y);
ctx.rotate(xAxisRotation);
ctx.scale(sx, sy);
ctx.arc(0, 0, r, a1, a1 + ad, 1 - sweepFlag);
ctx.scale(1/sx, 1/sy);
ctx.rotate(-xAxisRotation);
ctx.translate(-centp.x, -centp.y);
}
}
break;
case 'Z':
case 'z':
if (ctx != null) ctx.closePath();
pp.current = pp.start;
}
}
 
return bb;
}
 
this.getMarkers = function() {
var points = this.PathParser.getMarkerPoints();
var angles = this.PathParser.getMarkerAngles();
 
var markers = [];
for (var i=0; i<points.length; i++) {
markers.push([points[i], angles[i]]);
}
return markers;
}
}
svg.Element.path.prototype = new svg.Element.PathElementBase;
 
// pattern element
svg.Element.pattern = function(node) {
this.base = svg.Element.ElementBase;
this.base(node);
 
this.createPattern = function(ctx, element) {
var width = this.attribute('width').toPixels('x', true);
var height = this.attribute('height').toPixels('y', true);
 
// render me using a temporary svg element
var tempSvg = new svg.Element.svg();
tempSvg.attributes['viewBox'] = new svg.Property('viewBox', this.attribute('viewBox').value);
tempSvg.attributes['width'] = new svg.Property('width', width + 'px');
tempSvg.attributes['height'] = new svg.Property('height', height + 'px');
tempSvg.attributes['transform'] = new svg.Property('transform', this.attribute('patternTransform').value);
tempSvg.children = this.children;
 
var c = document.createElement('canvas');
c.width = width;
c.height = height;
var cctx = c.getContext('2d');
if (this.attribute('x').hasValue() && this.attribute('y').hasValue()) {
cctx.translate(this.attribute('x').toPixels('x', true), this.attribute('y').toPixels('y', true));
}
// render 3x3 grid so when we transform there's no white space on edges
for (var x=-1; x<=1; x++) {
for (var y=-1; y<=1; y++) {
cctx.save();
tempSvg.attributes['x'] = new svg.Property('x', x * c.width);
tempSvg.attributes['y'] = new svg.Property('y', y * c.height);
tempSvg.render(cctx);
cctx.restore();
}
}
var pattern = ctx.createPattern(c, 'repeat');
return pattern;
}
}
svg.Element.pattern.prototype = new svg.Element.ElementBase;
 
// marker element
svg.Element.marker = function(node) {
this.base = svg.Element.ElementBase;
this.base(node);
 
this.baseRender = this.render;
this.render = function(ctx, point, angle) {
ctx.translate(point.x, point.y);
if (this.attribute('orient').valueOrDefault('auto') == 'auto') ctx.rotate(angle);
if (this.attribute('markerUnits').valueOrDefault('strokeWidth') == 'strokeWidth') ctx.scale(ctx.lineWidth, ctx.lineWidth);
ctx.save();
 
// render me using a temporary svg element
var tempSvg = new svg.Element.svg();
tempSvg.attributes['viewBox'] = new svg.Property('viewBox', this.attribute('viewBox').value);
tempSvg.attributes['refX'] = new svg.Property('refX', this.attribute('refX').value);
tempSvg.attributes['refY'] = new svg.Property('refY', this.attribute('refY').value);
tempSvg.attributes['width'] = new svg.Property('width', this.attribute('markerWidth').value);
tempSvg.attributes['height'] = new svg.Property('height', this.attribute('markerHeight').value);
tempSvg.attributes['fill'] = new svg.Property('fill', this.attribute('fill').valueOrDefault('black'));
tempSvg.attributes['stroke'] = new svg.Property('stroke', this.attribute('stroke').valueOrDefault('none'));
tempSvg.children = this.children;
tempSvg.render(ctx);
 
ctx.restore();
if (this.attribute('markerUnits').valueOrDefault('strokeWidth') == 'strokeWidth') ctx.scale(1/ctx.lineWidth, 1/ctx.lineWidth);
if (this.attribute('orient').valueOrDefault('auto') == 'auto') ctx.rotate(-angle);
ctx.translate(-point.x, -point.y);
}
}
svg.Element.marker.prototype = new svg.Element.ElementBase;
 
// definitions element
svg.Element.defs = function(node) {
this.base = svg.Element.ElementBase;
this.base(node);
 
this.render = function(ctx) {
// NOOP
}
}
svg.Element.defs.prototype = new svg.Element.ElementBase;
 
// base for gradients
svg.Element.GradientBase = function(node) {
this.base = svg.Element.ElementBase;
this.base(node);
 
this.stops = [];
for (var i=0; i<this.children.length; i++) {
var child = this.children[i];
if (child.type == 'stop') this.stops.push(child);
}
 
this.getGradient = function() {
// OVERRIDE ME!
}
this.gradientUnits = function () {
return this.attribute('gradientUnits').valueOrDefault('objectBoundingBox');
}
this.attributesToInherit = ['gradientUnits'];
this.inheritStopContainer = function (stopsContainer) {
for (var i=0; i<this.attributesToInherit.length; i++) {
var attributeToInherit = this.attributesToInherit[i];
if (!this.attribute(attributeToInherit).hasValue() && stopsContainer.attribute(attributeToInherit).hasValue()) {
this.attribute(attributeToInherit, true).value = stopsContainer.attribute(attributeToInherit).value;
}
}
}
 
this.createGradient = function(ctx, element, parentOpacityProp) {
var stopsContainer = this;
if (this.getHrefAttribute().hasValue()) {
stopsContainer = this.getHrefAttribute().getDefinition();
this.inheritStopContainer(stopsContainer);
}
 
var addParentOpacity = function (color) {
if (parentOpacityProp.hasValue()) {
var p = new svg.Property('color', color);
return p.addOpacity(parentOpacityProp).value;
}
return color;
};
 
var g = this.getGradient(ctx, element);
if (g == null) return addParentOpacity(stopsContainer.stops[stopsContainer.stops.length - 1].color);
for (var i=0; i<stopsContainer.stops.length; i++) {
g.addColorStop(stopsContainer.stops[i].offset, addParentOpacity(stopsContainer.stops[i].color));
}
 
if (this.attribute('gradientTransform').hasValue()) {
// render as transformed pattern on temporary canvas
var rootView = svg.ViewPort.viewPorts[0];
 
var rect = new svg.Element.rect();
rect.attributes['x'] = new svg.Property('x', -svg.MAX_VIRTUAL_PIXELS/3.0);
rect.attributes['y'] = new svg.Property('y', -svg.MAX_VIRTUAL_PIXELS/3.0);
rect.attributes['width'] = new svg.Property('width', svg.MAX_VIRTUAL_PIXELS);
rect.attributes['height'] = new svg.Property('height', svg.MAX_VIRTUAL_PIXELS);
 
var group = new svg.Element.g();
group.attributes['transform'] = new svg.Property('transform', this.attribute('gradientTransform').value);
group.children = [ rect ];
 
var tempSvg = new svg.Element.svg();
tempSvg.attributes['x'] = new svg.Property('x', 0);
tempSvg.attributes['y'] = new svg.Property('y', 0);
tempSvg.attributes['width'] = new svg.Property('width', rootView.width);
tempSvg.attributes['height'] = new svg.Property('height', rootView.height);
tempSvg.children = [ group ];
 
var c = document.createElement('canvas');
c.width = rootView.width;
c.height = rootView.height;
var tempCtx = c.getContext('2d');
tempCtx.fillStyle = g;
tempSvg.render(tempCtx);
return tempCtx.createPattern(c, 'no-repeat');
}
 
return g;
}
}
svg.Element.GradientBase.prototype = new svg.Element.ElementBase;
 
// linear gradient element
svg.Element.linearGradient = function(node) {
this.base = svg.Element.GradientBase;
this.base(node);
this.attributesToInherit.push('x1');
this.attributesToInherit.push('y1');
this.attributesToInherit.push('x2');
this.attributesToInherit.push('y2');
 
this.getGradient = function(ctx, element) {
var bb = this.gradientUnits() == 'objectBoundingBox' ? element.getBoundingBox() : null;
 
if (!this.attribute('x1').hasValue()
&& !this.attribute('y1').hasValue()
&& !this.attribute('x2').hasValue()
&& !this.attribute('y2').hasValue()) {
this.attribute('x1', true).value = 0;
this.attribute('y1', true).value = 0;
this.attribute('x2', true).value = 1;
this.attribute('y2', true).value = 0;
}
 
var x1 = (this.gradientUnits() == 'objectBoundingBox'
? bb.x() + bb.width() * this.attribute('x1').numValue()
: this.attribute('x1').toPixels('x'));
var y1 = (this.gradientUnits() == 'objectBoundingBox'
? bb.y() + bb.height() * this.attribute('y1').numValue()
: this.attribute('y1').toPixels('y'));
var x2 = (this.gradientUnits() == 'objectBoundingBox'
? bb.x() + bb.width() * this.attribute('x2').numValue()
: this.attribute('x2').toPixels('x'));
var y2 = (this.gradientUnits() == 'objectBoundingBox'
? bb.y() + bb.height() * this.attribute('y2').numValue()
: this.attribute('y2').toPixels('y'));
 
if (x1 == x2 && y1 == y2) return null;
return ctx.createLinearGradient(x1, y1, x2, y2);
}
}
svg.Element.linearGradient.prototype = new svg.Element.GradientBase;
 
// radial gradient element
svg.Element.radialGradient = function(node) {
this.base = svg.Element.GradientBase;
this.base(node);
this.attributesToInherit.push('cx');
this.attributesToInherit.push('cy');
this.attributesToInherit.push('r');
this.attributesToInherit.push('fx');
this.attributesToInherit.push('fy');
 
this.getGradient = function(ctx, element) {
var bb = element.getBoundingBox();
 
if (!this.attribute('cx').hasValue()) this.attribute('cx', true).value = '50%';
if (!this.attribute('cy').hasValue()) this.attribute('cy', true).value = '50%';
if (!this.attribute('r').hasValue()) this.attribute('r', true).value = '50%';
 
var cx = (this.gradientUnits() == 'objectBoundingBox'
? bb.x() + bb.width() * this.attribute('cx').numValue()
: this.attribute('cx').toPixels('x'));
var cy = (this.gradientUnits() == 'objectBoundingBox'
? bb.y() + bb.height() * this.attribute('cy').numValue()
: this.attribute('cy').toPixels('y'));
 
var fx = cx;
var fy = cy;
if (this.attribute('fx').hasValue()) {
fx = (this.gradientUnits() == 'objectBoundingBox'
? bb.x() + bb.width() * this.attribute('fx').numValue()
: this.attribute('fx').toPixels('x'));
}
if (this.attribute('fy').hasValue()) {
fy = (this.gradientUnits() == 'objectBoundingBox'
? bb.y() + bb.height() * this.attribute('fy').numValue()
: this.attribute('fy').toPixels('y'));
}
 
var r = (this.gradientUnits() == 'objectBoundingBox'
? (bb.width() + bb.height()) / 2.0 * this.attribute('r').numValue()
: this.attribute('r').toPixels());
 
return ctx.createRadialGradient(fx, fy, 0, cx, cy, r);
}
}
svg.Element.radialGradient.prototype = new svg.Element.GradientBase;
 
// gradient stop element
svg.Element.stop = function(node) {
this.base = svg.Element.ElementBase;
this.base(node);
 
this.offset = this.attribute('offset').numValue();
if (this.offset < 0) this.offset = 0;
if (this.offset > 1) this.offset = 1;
 
var stopColor = this.style('stop-color', true);
if (stopColor.value === '') stopColor.value = '#000';
if (this.style('stop-opacity').hasValue()) stopColor = stopColor.addOpacity(this.style('stop-opacity'));
this.color = stopColor.value;
}
svg.Element.stop.prototype = new svg.Element.ElementBase;
 
// animation base element
svg.Element.AnimateBase = function(node) {
this.base = svg.Element.ElementBase;
this.base(node);
 
svg.Animations.push(this);
 
this.duration = 0.0;
this.begin = this.attribute('begin').toMilliseconds();
this.maxDuration = this.begin + this.attribute('dur').toMilliseconds();
 
this.getProperty = function() {
var attributeType = this.attribute('attributeType').value;
var attributeName = this.attribute('attributeName').value;
 
if (attributeType == 'CSS') {
return this.parent.style(attributeName, true);
}
return this.parent.attribute(attributeName, true);
};
 
this.initialValue = null;
this.initialUnits = '';
this.removed = false;
 
this.calcValue = function() {
// OVERRIDE ME!
return '';
}
 
this.update = function(delta) {
// set initial value
if (this.initialValue == null) {
this.initialValue = this.getProperty().value;
this.initialUnits = this.getProperty().getUnits();
}
 
// if we're past the end time
if (this.duration > this.maxDuration) {
// loop for indefinitely repeating animations
if (this.attribute('repeatCount').value == 'indefinite'
|| this.attribute('repeatDur').value == 'indefinite') {
this.duration = 0.0
}
else if (this.attribute('fill').valueOrDefault('remove') == 'freeze' && !this.frozen) {
this.frozen = true;
this.parent.animationFrozen = true;
this.parent.animationFrozenValue = this.getProperty().value;
}
else if (this.attribute('fill').valueOrDefault('remove') == 'remove' && !this.removed) {
this.removed = true;
this.getProperty().value = this.parent.animationFrozen ? this.parent.animationFrozenValue : this.initialValue;
return true;
}
return false;
}
this.duration = this.duration + delta;
 
// if we're past the begin time
var updated = false;
if (this.begin < this.duration) {
var newValue = this.calcValue(); // tween
 
if (this.attribute('type').hasValue()) {
// for transform, etc.
var type = this.attribute('type').value;
newValue = type + '(' + newValue + ')';
}
 
this.getProperty().value = newValue;
updated = true;
}
 
return updated;
}
 
this.from = this.attribute('from');
this.to = this.attribute('to');
this.values = this.attribute('values');
if (this.values.hasValue()) this.values.value = this.values.value.split(';');
 
// fraction of duration we've covered
this.progress = function() {
var ret = { progress: (this.duration - this.begin) / (this.maxDuration - this.begin) };
if (this.values.hasValue()) {
var p = ret.progress * (this.values.value.length - 1);
var lb = Math.floor(p), ub = Math.ceil(p);
ret.from = new svg.Property('from', parseFloat(this.values.value[lb]));
ret.to = new svg.Property('to', parseFloat(this.values.value[ub]));
ret.progress = (p - lb) / (ub - lb);
}
else {
ret.from = this.from;
ret.to = this.to;
}
return ret;
}
}
svg.Element.AnimateBase.prototype = new svg.Element.ElementBase;
 
// animate element
svg.Element.animate = function(node) {
this.base = svg.Element.AnimateBase;
this.base(node);
 
this.calcValue = function() {
var p = this.progress();
 
// tween value linearly
var newValue = p.from.numValue() + (p.to.numValue() - p.from.numValue()) * p.progress;
return newValue + this.initialUnits;
};
}
svg.Element.animate.prototype = new svg.Element.AnimateBase;
 
// animate color element
svg.Element.animateColor = function(node) {
this.base = svg.Element.AnimateBase;
this.base(node);
 
this.calcValue = function() {
var p = this.progress();
var from = new RGBColor(p.from.value);
var to = new RGBColor(p.to.value);
 
if (from.ok && to.ok) {
// tween color linearly
var r = from.r + (to.r - from.r) * p.progress;
var g = from.g + (to.g - from.g) * p.progress;
var b = from.b + (to.b - from.b) * p.progress;
return 'rgb('+parseInt(r,10)+','+parseInt(g,10)+','+parseInt(b,10)+')';
}
return this.attribute('from').value;
};
}
svg.Element.animateColor.prototype = new svg.Element.AnimateBase;
 
// animate transform element
svg.Element.animateTransform = function(node) {
this.base = svg.Element.AnimateBase;
this.base(node);
 
this.calcValue = function() {
var p = this.progress();
 
// tween value linearly
var from = svg.ToNumberArray(p.from.value);
var to = svg.ToNumberArray(p.to.value);
var newValue = '';
for (var i=0; i<from.length; i++) {
newValue += from[i] + (to[i] - from[i]) * p.progress + ' ';
}
return newValue;
};
}
svg.Element.animateTransform.prototype = new svg.Element.animate;
 
// font element
svg.Element.font = function(node) {
this.base = svg.Element.ElementBase;
this.base(node);
 
this.horizAdvX = this.attribute('horiz-adv-x').numValue();
 
this.isRTL = false;
this.isArabic = false;
this.fontFace = null;
this.missingGlyph = null;
this.glyphs = [];
for (var i=0; i<this.children.length; i++) {
var child = this.children[i];
if (child.type == 'font-face') {
this.fontFace = child;
if (child.style('font-family').hasValue()) {
svg.Definitions[child.style('font-family').value] = this;
}
}
else if (child.type == 'missing-glyph') this.missingGlyph = child;
else if (child.type == 'glyph') {
if (child.arabicForm != '') {
this.isRTL = true;
this.isArabic = true;
if (typeof(this.glyphs[child.unicode]) == 'undefined') this.glyphs[child.unicode] = [];
this.glyphs[child.unicode][child.arabicForm] = child;
}
else {
this.glyphs[child.unicode] = child;
}
}
}
}
svg.Element.font.prototype = new svg.Element.ElementBase;
 
// font-face element
svg.Element.fontface = function(node) {
this.base = svg.Element.ElementBase;
this.base(node);
 
this.ascent = this.attribute('ascent').value;
this.descent = this.attribute('descent').value;
this.unitsPerEm = this.attribute('units-per-em').numValue();
}
svg.Element.fontface.prototype = new svg.Element.ElementBase;
 
// missing-glyph element
svg.Element.missingglyph = function(node) {
this.base = svg.Element.path;
this.base(node);
 
this.horizAdvX = 0;
}
svg.Element.missingglyph.prototype = new svg.Element.path;
 
// glyph element
svg.Element.glyph = function(node) {
this.base = svg.Element.path;
this.base(node);
 
this.horizAdvX = this.attribute('horiz-adv-x').numValue();
this.unicode = this.attribute('unicode').value;
this.arabicForm = this.attribute('arabic-form').value;
}
svg.Element.glyph.prototype = new svg.Element.path;
 
// text element
svg.Element.text = function(node) {
this.captureTextNodes = true;
this.base = svg.Element.RenderedElementBase;
this.base(node);
 
this.baseSetContext = this.setContext;
this.setContext = function(ctx) {
this.baseSetContext(ctx);
 
var textBaseline = this.style('dominant-baseline').toTextBaseline();
if (textBaseline == null) textBaseline = this.style('alignment-baseline').toTextBaseline();
if (textBaseline != null) ctx.textBaseline = textBaseline;
}
 
this.getBoundingBox = function () {
var x = this.attribute('x').toPixels('x');
var y = this.attribute('y').toPixels('y');
var fontSize = this.parent.style('font-size').numValueOrDefault(svg.Font.Parse(svg.ctx.font).fontSize);
return new svg.BoundingBox(x, y - fontSize, x + Math.floor(fontSize * 2.0 / 3.0) * this.children[0].getText().length, y);
}
 
this.renderChildren = function(ctx) {
this.x = this.attribute('x').toPixels('x');
this.y = this.attribute('y').toPixels('y');
if (this.attribute('dx').hasValue()) this.x += this.attribute('dx').toPixels('x');
if (this.attribute('dy').hasValue()) this.y += this.attribute('dy').toPixels('y');
this.x += this.getAnchorDelta(ctx, this, 0);
for (var i=0; i<this.children.length; i++) {
this.renderChild(ctx, this, i);
}
}
 
this.getAnchorDelta = function (ctx, parent, startI) {
var textAnchor = this.style('text-anchor').valueOrDefault('start');
if (textAnchor != 'start') {
var width = 0;
for (var i=startI; i<parent.children.length; i++) {
var child = parent.children[i];
if (i > startI && child.attribute('x').hasValue()) break; // new group
width += child.measureTextRecursive(ctx);
}
return -1 * (textAnchor == 'end' ? width : width / 2.0);
}
return 0;
}
 
this.renderChild = function(ctx, parent, i) {
var child = parent.children[i];
if (child.attribute('x').hasValue()) {
child.x = child.attribute('x').toPixels('x') + parent.getAnchorDelta(ctx, parent, i);
if (child.attribute('dx').hasValue()) child.x += child.attribute('dx').toPixels('x');
}
else {
if (child.attribute('dx').hasValue()) parent.x += child.attribute('dx').toPixels('x');
child.x = parent.x;
}
parent.x = child.x + child.measureText(ctx);
 
if (child.attribute('y').hasValue()) {
child.y = child.attribute('y').toPixels('y');
if (child.attribute('dy').hasValue()) child.y += child.attribute('dy').toPixels('y');
}
else {
if (child.attribute('dy').hasValue()) parent.y += child.attribute('dy').toPixels('y');
child.y = parent.y;
}
parent.y = child.y;
 
child.render(ctx);
 
for (var i=0; i<child.children.length; i++) {
parent.renderChild(ctx, child, i);
}
}
}
svg.Element.text.prototype = new svg.Element.RenderedElementBase;
 
// text base
svg.Element.TextElementBase = function(node) {
this.base = svg.Element.RenderedElementBase;
this.base(node);
 
this.getGlyph = function(font, text, i) {
var c = text[i];
var glyph = null;
if (font.isArabic) {
var arabicForm = 'isolated';
if ((i==0 || text[i-1]==' ') && i<text.length-2 && text[i+1]!=' ') arabicForm = 'terminal';
if (i>0 && text[i-1]!=' ' && i<text.length-2 && text[i+1]!=' ') arabicForm = 'medial';
if (i>0 && text[i-1]!=' ' && (i == text.length-1 || text[i+1]==' ')) arabicForm = 'initial';
if (typeof(font.glyphs[c]) != 'undefined') {
glyph = font.glyphs[c][arabicForm];
if (glyph == null && font.glyphs[c].type == 'glyph') glyph = font.glyphs[c];
}
}
else {
glyph = font.glyphs[c];
}
if (glyph == null) glyph = font.missingGlyph;
return glyph;
}
 
this.renderChildren = function(ctx) {
var customFont = this.parent.style('font-family').getDefinition();
if (customFont != null) {
var fontSize = this.parent.style('font-size').numValueOrDefault(svg.Font.Parse(svg.ctx.font).fontSize);
var fontStyle = this.parent.style('font-style').valueOrDefault(svg.Font.Parse(svg.ctx.font).fontStyle);
var text = this.getText();
if (customFont.isRTL) text = text.split("").reverse().join("");
 
var dx = svg.ToNumberArray(this.parent.attribute('dx').value);
for (var i=0; i<text.length; i++) {
var glyph = this.getGlyph(customFont, text, i);
var scale = fontSize / customFont.fontFace.unitsPerEm;
ctx.translate(this.x, this.y);
ctx.scale(scale, -scale);
var lw = ctx.lineWidth;
ctx.lineWidth = ctx.lineWidth * customFont.fontFace.unitsPerEm / fontSize;
if (fontStyle == 'italic') ctx.transform(1, 0, .4, 1, 0, 0);
glyph.render(ctx);
if (fontStyle == 'italic') ctx.transform(1, 0, -.4, 1, 0, 0);
ctx.lineWidth = lw;
ctx.scale(1/scale, -1/scale);
ctx.translate(-this.x, -this.y);
 
this.x += fontSize * (glyph.horizAdvX || customFont.horizAdvX) / customFont.fontFace.unitsPerEm;
if (typeof(dx[i]) != 'undefined' && !isNaN(dx[i])) {
this.x += dx[i];
}
}
return;
}
 
if (ctx.fillStyle != '') ctx.fillText(svg.compressSpaces(this.getText()), this.x, this.y);
if (ctx.strokeStyle != '') ctx.strokeText(svg.compressSpaces(this.getText()), this.x, this.y);
}
 
this.getText = function() {
// OVERRIDE ME
}
 
this.measureTextRecursive = function(ctx) {
var width = this.measureText(ctx);
for (var i=0; i<this.children.length; i++) {
width += this.children[i].measureTextRecursive(ctx);
}
return width;
}
 
this.measureText = function(ctx) {
var customFont = this.parent.style('font-family').getDefinition();
if (customFont != null) {
var fontSize = this.parent.style('font-size').numValueOrDefault(svg.Font.Parse(svg.ctx.font).fontSize);
var measure = 0;
var text = this.getText();
if (customFont.isRTL) text = text.split("").reverse().join("");
var dx = svg.ToNumberArray(this.parent.attribute('dx').value);
for (var i=0; i<text.length; i++) {
var glyph = this.getGlyph(customFont, text, i);
measure += (glyph.horizAdvX || customFont.horizAdvX) * fontSize / customFont.fontFace.unitsPerEm;
if (typeof(dx[i]) != 'undefined' && !isNaN(dx[i])) {
measure += dx[i];
}
}
return measure;
}
 
var textToMeasure = svg.compressSpaces(this.getText());
if (!ctx.measureText) return textToMeasure.length * 10;
 
ctx.save();
this.setContext(ctx);
var width = ctx.measureText(textToMeasure).width;
ctx.restore();
return width;
}
}
svg.Element.TextElementBase.prototype = new svg.Element.RenderedElementBase;
 
// tspan
svg.Element.tspan = function(node) {
this.captureTextNodes = true;
this.base = svg.Element.TextElementBase;
this.base(node);
 
this.text = svg.compressSpaces(node.value || node.text || node.textContent || '');
this.getText = function() {
// if this node has children, then they own the text
if (this.children.length > 0) { return ''; }
return this.text;
}
}
svg.Element.tspan.prototype = new svg.Element.TextElementBase;
 
// tref
svg.Element.tref = function(node) {
this.base = svg.Element.TextElementBase;
this.base(node);
 
this.getText = function() {
var element = this.getHrefAttribute().getDefinition();
if (element != null) return element.children[0].getText();
}
}
svg.Element.tref.prototype = new svg.Element.TextElementBase;
 
// a element
svg.Element.a = function(node) {
this.base = svg.Element.TextElementBase;
this.base(node);
 
this.hasText = node.childNodes.length > 0;
for (var i=0; i<node.childNodes.length; i++) {
if (node.childNodes[i].nodeType != 3) this.hasText = false;
}
 
// this might contain text
this.text = this.hasText ? node.childNodes[0].value : '';
this.getText = function() {
return this.text;
}
 
this.baseRenderChildren = this.renderChildren;
this.renderChildren = function(ctx) {
if (this.hasText) {
// render as text element
this.baseRenderChildren(ctx);
var fontSize = new svg.Property('fontSize', svg.Font.Parse(svg.ctx.font).fontSize);
svg.Mouse.checkBoundingBox(this, new svg.BoundingBox(this.x, this.y - fontSize.toPixels('y'), this.x + this.measureText(ctx), this.y));
}
else if (this.children.length > 0) {
// render as temporary group
var g = new svg.Element.g();
g.children = this.children;
g.parent = this;
g.render(ctx);
}
}
 
this.onclick = function() {
window.open(this.getHrefAttribute().value);
}
 
this.onmousemove = function() {
svg.ctx.canvas.style.cursor = 'pointer';
}
}
svg.Element.a.prototype = new svg.Element.TextElementBase;
 
// image element
svg.Element.image = function(node) {
this.base = svg.Element.RenderedElementBase;
this.base(node);
 
var href = this.getHrefAttribute().value;
if (href == '') { return; }
var isSvg = href.match(/\.svg$/)
 
svg.Images.push(this);
this.loaded = false;
if (!isSvg) {
this.img = document.createElement('img');
if (svg.opts['useCORS'] == true) { this.img.crossOrigin = 'Anonymous'; }
var self = this;
this.img.onload = function() { self.loaded = true; }
this.img.onerror = function() { svg.log('ERROR: image "' + href + '" not found'); self.loaded = true; }
this.img.src = href;
}
else {
this.img = svg.ajax(href);
this.loaded = true;
}
 
this.renderChildren = function(ctx) {
var x = this.attribute('x').toPixels('x');
var y = this.attribute('y').toPixels('y');
 
var width = this.attribute('width').toPixels('x');
var height = this.attribute('height').toPixels('y');
if (width == 0 || height == 0) return;
 
ctx.save();
if (isSvg) {
ctx.drawSvg(this.img, x, y, width, height);
}
else {
ctx.translate(x, y);
svg.AspectRatio(ctx,
this.attribute('preserveAspectRatio').value,
width,
this.img.width,
height,
this.img.height,
0,
0);
ctx.drawImage(this.img, 0, 0);
}
ctx.restore();
}
 
this.getBoundingBox = function() {
var x = this.attribute('x').toPixels('x');
var y = this.attribute('y').toPixels('y');
var width = this.attribute('width').toPixels('x');
var height = this.attribute('height').toPixels('y');
return new svg.BoundingBox(x, y, x + width, y + height);
}
}
svg.Element.image.prototype = new svg.Element.RenderedElementBase;
 
// group element
svg.Element.g = function(node) {
this.base = svg.Element.RenderedElementBase;
this.base(node);
 
this.getBoundingBox = function() {
var bb = new svg.BoundingBox();
for (var i=0; i<this.children.length; i++) {
bb.addBoundingBox(this.children[i].getBoundingBox());
}
return bb;
};
}
svg.Element.g.prototype = new svg.Element.RenderedElementBase;
 
// symbol element
svg.Element.symbol = function(node) {
this.base = svg.Element.RenderedElementBase;
this.base(node);
 
this.render = function(ctx) {
// NO RENDER
};
}
svg.Element.symbol.prototype = new svg.Element.RenderedElementBase;
 
// style element
svg.Element.style = function(node) {
this.base = svg.Element.ElementBase;
this.base(node);
 
// text, or spaces then CDATA
var css = ''
for (var i=0; i<node.childNodes.length; i++) {
css += node.childNodes[i].data;
}
css = css.replace(/(\/\*([^*]|[\r\n]|(\*+([^*\/]|[\r\n])))*\*+\/)|(^[\s]*\/\/.*)/gm, ''); // remove comments
css = svg.compressSpaces(css); // replace whitespace
var cssDefs = css.split('}');
for (var i=0; i<cssDefs.length; i++) {
if (svg.trim(cssDefs[i]) != '') {
var cssDef = cssDefs[i].split('{');
var cssClasses = cssDef[0].split(',');
var cssProps = cssDef[1].split(';');
for (var j=0; j<cssClasses.length; j++) {
var cssClass = svg.trim(cssClasses[j]);
if (cssClass != '') {
var props = svg.Styles[cssClass] || {};
for (var k=0; k<cssProps.length; k++) {
var prop = cssProps[k].indexOf(':');
var name = cssProps[k].substr(0, prop);
var value = cssProps[k].substr(prop + 1, cssProps[k].length - prop);
if (name != null && value != null) {
props[svg.trim(name)] = new svg.Property(svg.trim(name), svg.trim(value));
}
}
svg.Styles[cssClass] = props;
svg.StylesSpecificity[cssClass] = getSelectorSpecificity(cssClass);
if (cssClass == '@font-face') {
var fontFamily = props['font-family'].value.replace(/"/g,'');
var srcs = props['src'].value.split(',');
for (var s=0; s<srcs.length; s++) {
if (srcs[s].indexOf('format("svg")') > 0) {
var urlStart = srcs[s].indexOf('url');
var urlEnd = srcs[s].indexOf(')', urlStart);
var url = srcs[s].substr(urlStart + 5, urlEnd - urlStart - 6);
var doc = svg.parseXml(svg.ajax(url));
var fonts = doc.getElementsByTagName('font');
for (var f=0; f<fonts.length; f++) {
var font = svg.CreateElement(fonts[f]);
svg.Definitions[fontFamily] = font;
}
}
}
}
}
}
}
}
}
svg.Element.style.prototype = new svg.Element.ElementBase;
 
// use element
svg.Element.use = function(node) {
this.base = svg.Element.RenderedElementBase;
this.base(node);
 
this.baseSetContext = this.setContext;
this.setContext = function(ctx) {
this.baseSetContext(ctx);
if (this.attribute('x').hasValue()) ctx.translate(this.attribute('x').toPixels('x'), 0);
if (this.attribute('y').hasValue()) ctx.translate(0, this.attribute('y').toPixels('y'));
}
 
var element = this.getHrefAttribute().getDefinition();
 
this.path = function(ctx) {
if (element != null) element.path(ctx);
}
 
this.getBoundingBox = function() {
if (element != null) return element.getBoundingBox();
}
 
this.renderChildren = function(ctx) {
if (element != null) {
var tempSvg = element;
if (element.type == 'symbol') {
// render me using a temporary svg element in symbol cases (http://www.w3.org/TR/SVG/struct.html#UseElement)
tempSvg = new svg.Element.svg();
tempSvg.type = 'svg';
tempSvg.attributes['viewBox'] = new svg.Property('viewBox', element.attribute('viewBox').value);
tempSvg.attributes['preserveAspectRatio'] = new svg.Property('preserveAspectRatio', element.attribute('preserveAspectRatio').value);
tempSvg.attributes['overflow'] = new svg.Property('overflow', element.attribute('overflow').value);
tempSvg.children = element.children;
}
if (tempSvg.type == 'svg') {
// if symbol or svg, inherit width/height from me
if (this.attribute('width').hasValue()) tempSvg.attributes['width'] = new svg.Property('width', this.attribute('width').value);
if (this.attribute('height').hasValue()) tempSvg.attributes['height'] = new svg.Property('height', this.attribute('height').value);
}
var oldParent = tempSvg.parent;
tempSvg.parent = null;
tempSvg.render(ctx);
tempSvg.parent = oldParent;
}
}
}
svg.Element.use.prototype = new svg.Element.RenderedElementBase;
 
// mask element
svg.Element.mask = function(node) {
this.base = svg.Element.ElementBase;
this.base(node);
 
this.apply = function(ctx, element) {
// render as temp svg
var x = this.attribute('x').toPixels('x');
var y = this.attribute('y').toPixels('y');
var width = this.attribute('width').toPixels('x');
var height = this.attribute('height').toPixels('y');
 
if (width == 0 && height == 0) {
var bb = new svg.BoundingBox();
for (var i=0; i<this.children.length; i++) {
bb.addBoundingBox(this.children[i].getBoundingBox());
}
var x = Math.floor(bb.x1);
var y = Math.floor(bb.y1);
var width = Math.floor(bb.width());
var height = Math.floor(bb.height());
}
 
// temporarily remove mask to avoid recursion
var mask = element.attribute('mask').value;
element.attribute('mask').value = '';
 
var cMask = document.createElement('canvas');
cMask.width = x + width;
cMask.height = y + height;
var maskCtx = cMask.getContext('2d');
this.renderChildren(maskCtx);
 
var c = document.createElement('canvas');
c.width = x + width;
c.height = y + height;
var tempCtx = c.getContext('2d');
element.render(tempCtx);
tempCtx.globalCompositeOperation = 'destination-in';
tempCtx.fillStyle = maskCtx.createPattern(cMask, 'no-repeat');
tempCtx.fillRect(0, 0, x + width, y + height);
 
ctx.fillStyle = tempCtx.createPattern(c, 'no-repeat');
ctx.fillRect(0, 0, x + width, y + height);
 
// reassign mask
element.attribute('mask').value = mask;
}
 
this.render = function(ctx) {
// NO RENDER
}
}
svg.Element.mask.prototype = new svg.Element.ElementBase;
 
// clip element
svg.Element.clipPath = function(node) {
this.base = svg.Element.ElementBase;
this.base(node);
 
this.apply = function(ctx) {
var oldBeginPath = CanvasRenderingContext2D.prototype.beginPath;
CanvasRenderingContext2D.prototype.beginPath = function () { };
 
var oldClosePath = CanvasRenderingContext2D.prototype.closePath;
CanvasRenderingContext2D.prototype.closePath = function () { };
 
oldBeginPath.call(ctx);
for (var i=0; i<this.children.length; i++) {
var child = this.children[i];
if (typeof(child.path) != 'undefined') {
var transform = null;
if (child.style('transform', false, true).hasValue()) {
transform = new svg.Transform(child.style('transform', false, true).value);
transform.apply(ctx);
}
child.path(ctx);
CanvasRenderingContext2D.prototype.closePath = oldClosePath;
if (transform) { transform.unapply(ctx); }
}
}
oldClosePath.call(ctx);
ctx.clip();
 
CanvasRenderingContext2D.prototype.beginPath = oldBeginPath;
CanvasRenderingContext2D.prototype.closePath = oldClosePath;
}
 
this.render = function(ctx) {
// NO RENDER
}
}
svg.Element.clipPath.prototype = new svg.Element.ElementBase;
 
// filters
svg.Element.filter = function(node) {
this.base = svg.Element.ElementBase;
this.base(node);
 
this.apply = function(ctx, element) {
// render as temp svg
var bb = element.getBoundingBox();
var x = Math.floor(bb.x1);
var y = Math.floor(bb.y1);
var width = Math.floor(bb.width());
var height = Math.floor(bb.height());
 
// temporarily remove filter to avoid recursion
var filter = element.style('filter').value;
element.style('filter').value = '';
 
var px = 0, py = 0;
for (var i=0; i<this.children.length; i++) {
var efd = this.children[i].extraFilterDistance || 0;
px = Math.max(px, efd);
py = Math.max(py, efd);
}
 
var c = document.createElement('canvas');
c.width = width + 2*px;
c.height = height + 2*py;
var tempCtx = c.getContext('2d');
tempCtx.translate(-x + px, -y + py);
element.render(tempCtx);
 
// apply filters
for (var i=0; i<this.children.length; i++) {
if (typeof(this.children[i].apply) === 'function') {
this.children[i].apply(tempCtx, 0, 0, width + 2*px, height + 2*py);
}
}
 
// render on me
ctx.drawImage(c, 0, 0, width + 2*px, height + 2*py, x - px, y - py, width + 2*px, height + 2*py);
 
// reassign filter
element.style('filter', true).value = filter;
}
 
this.render = function(ctx) {
// NO RENDER
}
}
svg.Element.filter.prototype = new svg.Element.ElementBase;
 
svg.Element.feMorphology = function(node) {
this.base = svg.Element.ElementBase;
this.base(node);
 
this.apply = function(ctx, x, y, width, height) {
// TODO: implement
}
}
svg.Element.feMorphology.prototype = new svg.Element.ElementBase;
 
svg.Element.feComposite = function(node) {
this.base = svg.Element.ElementBase;
this.base(node);
 
this.apply = function(ctx, x, y, width, height) {
// TODO: implement
}
}
svg.Element.feComposite.prototype = new svg.Element.ElementBase;
 
svg.Element.feColorMatrix = function(node) {
this.base = svg.Element.ElementBase;
this.base(node);
 
var matrix = svg.ToNumberArray(this.attribute('values').value);
switch (this.attribute('type').valueOrDefault('matrix')) { // http://www.w3.org/TR/SVG/filters.html#feColorMatrixElement
case 'saturate':
var s = matrix[0];
matrix = [0.213+0.787*s,0.715-0.715*s,0.072-0.072*s,0,0,
0.213-0.213*s,0.715+0.285*s,0.072-0.072*s,0,0,
0.213-0.213*s,0.715-0.715*s,0.072+0.928*s,0,0,
0,0,0,1,0,
0,0,0,0,1];
break;
case 'hueRotate':
var a = matrix[0] * Math.PI / 180.0;
var c = function (m1,m2,m3) { return m1 + Math.cos(a)*m2 + Math.sin(a)*m3; };
matrix = [c(0.213,0.787,-0.213),c(0.715,-0.715,-0.715),c(0.072,-0.072,0.928),0,0,
c(0.213,-0.213,0.143),c(0.715,0.285,0.140),c(0.072,-0.072,-0.283),0,0,
c(0.213,-0.213,-0.787),c(0.715,-0.715,0.715),c(0.072,0.928,0.072),0,0,
0,0,0,1,0,
0,0,0,0,1];
break;
case 'luminanceToAlpha':
matrix = [0,0,0,0,0,
0,0,0,0,0,
0,0,0,0,0,
0.2125,0.7154,0.0721,0,0,
0,0,0,0,1];
break;
}
 
function imGet(img, x, y, width, height, rgba) {
return img[y*width*4 + x*4 + rgba];
}
 
function imSet(img, x, y, width, height, rgba, val) {
img[y*width*4 + x*4 + rgba] = val;
}
 
function m(i, v) {
var mi = matrix[i];
return mi * (mi < 0 ? v - 255 : v);
}
 
this.apply = function(ctx, x, y, width, height) {
// assuming x==0 && y==0 for now
var srcData = ctx.getImageData(0, 0, width, height);
for (var y = 0; y < height; y++) {
for (var x = 0; x < width; x++) {
var r = imGet(srcData.data, x, y, width, height, 0);
var g = imGet(srcData.data, x, y, width, height, 1);
var b = imGet(srcData.data, x, y, width, height, 2);
var a = imGet(srcData.data, x, y, width, height, 3);
imSet(srcData.data, x, y, width, height, 0, m(0,r)+m(1,g)+m(2,b)+m(3,a)+m(4,1));
imSet(srcData.data, x, y, width, height, 1, m(5,r)+m(6,g)+m(7,b)+m(8,a)+m(9,1));
imSet(srcData.data, x, y, width, height, 2, m(10,r)+m(11,g)+m(12,b)+m(13,a)+m(14,1));
imSet(srcData.data, x, y, width, height, 3, m(15,r)+m(16,g)+m(17,b)+m(18,a)+m(19,1));
}
}
ctx.clearRect(0, 0, width, height);
ctx.putImageData(srcData, 0, 0);
}
}
svg.Element.feColorMatrix.prototype = new svg.Element.ElementBase;
 
svg.Element.feGaussianBlur = function(node) {
this.base = svg.Element.ElementBase;
this.base(node);
 
this.blurRadius = Math.floor(this.attribute('stdDeviation').numValue());
this.extraFilterDistance = this.blurRadius;
 
this.apply = function(ctx, x, y, width, height) {
if (typeof(stackBlur.canvasRGBA) == 'undefined') {
svg.log('ERROR: StackBlur.js must be included for blur to work');
return;
}
 
// StackBlur requires canvas be on document
ctx.canvas.id = svg.UniqueId();
ctx.canvas.style.display = 'none';
document.body.appendChild(ctx.canvas);
stackBlur.canvasRGBA(ctx.canvas.id, x, y, width, height, this.blurRadius);
document.body.removeChild(ctx.canvas);
}
}
svg.Element.feGaussianBlur.prototype = new svg.Element.ElementBase;
 
// title element, do nothing
svg.Element.title = function(node) {
}
svg.Element.title.prototype = new svg.Element.ElementBase;
 
// desc element, do nothing
svg.Element.desc = function(node) {
}
svg.Element.desc.prototype = new svg.Element.ElementBase;
 
svg.Element.MISSING = function(node) {
svg.log('ERROR: Element \'' + node.nodeName + '\' not yet implemented.');
}
svg.Element.MISSING.prototype = new svg.Element.ElementBase;
 
// element factory
svg.CreateElement = function(node) {
var className = node.nodeName.replace(/^[^:]+:/,''); // remove namespace
className = className.replace(/\-/g,''); // remove dashes
var e = null;
if (typeof(svg.Element[className]) != 'undefined') {
e = new svg.Element[className](node);
}
else {
e = new svg.Element.MISSING(node);
}
 
e.type = node.nodeName;
return e;
}
 
// load from url
svg.load = function(ctx, url) {
svg.loadXml(ctx, svg.ajax(url));
}
 
// load from xml
svg.loadXml = function(ctx, xml) {
svg.loadXmlDoc(ctx, svg.parseXml(xml));
}
 
svg.loadXmlDoc = function(ctx, dom) {
svg.init(ctx);
 
var mapXY = function(p) {
var e = ctx.canvas;
while (e) {
p.x -= e.offsetLeft;
p.y -= e.offsetTop;
e = e.offsetParent;
}
if (window.scrollX) p.x += window.scrollX;
if (window.scrollY) p.y += window.scrollY;
return p;
}
 
// bind mouse
if (svg.opts['ignoreMouse'] != true) {
ctx.canvas.onclick = function(e) {
var p = mapXY(new svg.Point(e != null ? e.clientX : event.clientX, e != null ? e.clientY : event.clientY));
svg.Mouse.onclick(p.x, p.y);
};
ctx.canvas.onmousemove = function(e) {
var p = mapXY(new svg.Point(e != null ? e.clientX : event.clientX, e != null ? e.clientY : event.clientY));
svg.Mouse.onmousemove(p.x, p.y);
};
}
 
var e = svg.CreateElement(dom.documentElement);
e.root = true;
e.addStylesFromStyleDefinition();
 
// render loop
var isFirstRender = true;
var draw = function() {
svg.ViewPort.Clear();
if (ctx.canvas.parentNode) svg.ViewPort.SetCurrent(ctx.canvas.parentNode.clientWidth, ctx.canvas.parentNode.clientHeight);
 
if (svg.opts['ignoreDimensions'] != true) {
// set canvas size
if (e.style('width').hasValue()) {
ctx.canvas.width = e.style('width').toPixels('x');
ctx.canvas.style.width = ctx.canvas.width + 'px';
}
if (e.style('height').hasValue()) {
ctx.canvas.height = e.style('height').toPixels('y');
ctx.canvas.style.height = ctx.canvas.height + 'px';
}
}
var cWidth = ctx.canvas.clientWidth || ctx.canvas.width;
var cHeight = ctx.canvas.clientHeight || ctx.canvas.height;
if (svg.opts['ignoreDimensions'] == true && e.style('width').hasValue() && e.style('height').hasValue()) {
cWidth = e.style('width').toPixels('x');
cHeight = e.style('height').toPixels('y');
}
svg.ViewPort.SetCurrent(cWidth, cHeight);
 
if (svg.opts['offsetX'] != null) e.attribute('x', true).value = svg.opts['offsetX'];
if (svg.opts['offsetY'] != null) e.attribute('y', true).value = svg.opts['offsetY'];
if (svg.opts['scaleWidth'] != null || svg.opts['scaleHeight'] != null) {
var xRatio = null, yRatio = null, viewBox = svg.ToNumberArray(e.attribute('viewBox').value);
 
if (svg.opts['scaleWidth'] != null) {
if (e.attribute('width').hasValue()) xRatio = e.attribute('width').toPixels('x') / svg.opts['scaleWidth'];
else if (!isNaN(viewBox[2])) xRatio = viewBox[2] / svg.opts['scaleWidth'];
}
 
if (svg.opts['scaleHeight'] != null) {
if (e.attribute('height').hasValue()) yRatio = e.attribute('height').toPixels('y') / svg.opts['scaleHeight'];
else if (!isNaN(viewBox[3])) yRatio = viewBox[3] / svg.opts['scaleHeight'];
}
 
if (xRatio == null) { xRatio = yRatio; }
if (yRatio == null) { yRatio = xRatio; }
 
e.attribute('width', true).value = svg.opts['scaleWidth'];
e.attribute('height', true).value = svg.opts['scaleHeight'];
e.style('transform', true, true).value += ' scale('+(1.0/xRatio)+','+(1.0/yRatio)+')';
}
 
// clear and render
if (svg.opts['ignoreClear'] != true) {
ctx.clearRect(0, 0, cWidth, cHeight);
}
e.render(ctx);
if (isFirstRender) {
isFirstRender = false;
if (typeof(svg.opts['renderCallback']) == 'function') svg.opts['renderCallback'](dom);
}
}
 
var waitingForImages = true;
if (svg.ImagesLoaded()) {
waitingForImages = false;
draw();
}
svg.intervalID = setInterval(function() {
var needUpdate = false;
 
if (waitingForImages && svg.ImagesLoaded()) {
waitingForImages = false;
needUpdate = true;
}
 
// need update from mouse events?
if (svg.opts['ignoreMouse'] != true) {
needUpdate = needUpdate | svg.Mouse.hasEvents();
}
 
// need update from animations?
if (svg.opts['ignoreAnimation'] != true) {
for (var i=0; i<svg.Animations.length; i++) {
needUpdate = needUpdate | svg.Animations[i].update(1000 / svg.FRAMERATE);
}
}
 
// need update from redraw?
if (typeof(svg.opts['forceRedraw']) == 'function') {
if (svg.opts['forceRedraw']() == true) needUpdate = true;
}
 
// render if needed
if (needUpdate) {
draw();
svg.Mouse.runEvents(); // run and clear our events
}
}, 1000 / svg.FRAMERATE);
}
 
svg.stop = function() {
if (svg.intervalID) {
clearInterval(svg.intervalID);
}
}
 
svg.Mouse = new (function() {
this.events = [];
this.hasEvents = function() { return this.events.length != 0; }
 
this.onclick = function(x, y) {
this.events.push({ type: 'onclick', x: x, y: y,
run: function(e) { if (e.onclick) e.onclick(); }
});
}
 
this.onmousemove = function(x, y) {
this.events.push({ type: 'onmousemove', x: x, y: y,
run: function(e) { if (e.onmousemove) e.onmousemove(); }
});
}
 
this.eventElements = [];
 
this.checkPath = function(element, ctx) {
for (var i=0; i<this.events.length; i++) {
var e = this.events[i];
if (ctx.isPointInPath && ctx.isPointInPath(e.x, e.y)) this.eventElements[i] = element;
}
}
 
this.checkBoundingBox = function(element, bb) {
for (var i=0; i<this.events.length; i++) {
var e = this.events[i];
if (bb.isPointInBox(e.x, e.y)) this.eventElements[i] = element;
}
}
 
this.runEvents = function() {
svg.ctx.canvas.style.cursor = '';
 
for (var i=0; i<this.events.length; i++) {
var e = this.events[i];
var element = this.eventElements[i];
while (element) {
e.run(element);
element = element.parent;
}
}
 
// done running, clear
this.events = [];
this.eventElements = [];
}
});
 
return svg;
};
 
if (typeof(CanvasRenderingContext2D) != 'undefined') {
CanvasRenderingContext2D.prototype.drawSvg = function(s, dx, dy, dw, dh) {
canvg(this.canvas, s, {
ignoreMouse: true,
ignoreAnimation: true,
ignoreDimensions: true,
ignoreClear: true,
offsetX: dx,
offsetY: dy,
scaleWidth: dw,
scaleHeight: dh
});
}
}
 
return canvg;
 
}));
/base/000_base/node_modules/highcharts/lib/jspdf.js
@@ -0,0 +1,94 @@
/*
 
jsPDF - PDF Document creation from JavaScript
Version ${versionID}
CommitID ${commitID}
 
Copyright (c) 2010-2014 James Hall <james@parall.ax>, https://github.com/MrRio/jsPDF
2010 Aaron Spike, https://github.com/acspike
2012 Willow Systems Corporation, willow-systems.com
2012 Pablo Hess, https://github.com/pablohess
2012 Florian Jenett, https://github.com/fjenett
2013 Warren Weckesser, https://github.com/warrenweckesser
2013 Youssef Beddad, https://github.com/lifof
2013 Lee Driscoll, https://github.com/lsdriscoll
2013 Stefan Slonevskiy, https://github.com/stefslon
2013 Jeremy Morel, https://github.com/jmorel
2013 Christoph Hartmann, https://github.com/chris-rock
2014 Juan Pablo Gaviria, https://github.com/juanpgaviria
2014 James Makes, https://github.com/dollaruw
2014 Diego Casorran, https://github.com/diegocr
2014 Steven Spungin, https://github.com/Flamenco
2014 Kenneth Glassey, https://github.com/Gavvers
 
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
 
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
 
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 
Contributor(s):
siefkenj, ahwolf, rickygu, Midnith, saintclair, eaparango,
kim3er, mfo, alnorth, Flamenco
*/
var jsPDF=function(t){function Pa(q){var A={};this.subscribe=function(F,q,w){if("function"!==typeof q)return!1;A.hasOwnProperty(F)||(A[F]={});var t=Math.random().toString(35);A[F][t]=[q,!!w];return t};this.unsubscribe=function(q){for(var t in A)if(A[t][q])return delete A[t][q],!0;return!1};this.publish=function(F){if(A.hasOwnProperty(F)){var Z=Array.prototype.slice.call(arguments,1),w=[],S;for(S in A[F]){var aa=A[F][S];try{aa[0].apply(q,Z)}catch(ca){t.console&&console.error("jsPDF PubSub Error",ca.message,
ca)}aa[1]&&w.push(S)}w.length&&w.forEach(this.unsubscribe)}}}function q(V,A,F,Z){var w={};"object"===typeof V&&(w=V,V=w.orientation,A=w.unit||A,F=w.format||F,Z=w.compress||w.compressPdf||Z);A=A||"mm";F=F||"a4";V=(""+(V||"P")).toLowerCase();(""+F).toLowerCase();var S=!!Z&&"function"===typeof Uint8Array,aa=w.textColor||"0 g",ca=w.drawColor||"0 G",L=w.fontSize||16,oa=w.lineHeight||1.15,Qa=w.lineWidth||.200025,C=2,da=!1,N=[],r={},G={},D,Fa=[],u={},pa={},H={},qa={},Ga=null,E,z=0,I,m=[],J=[],B=[],ra=[],
W=[],sa=0,ta=0,P=0,M={},ea={},fa=[],ga,ha,ia,X,Q,ua,O,ja,T={title:"",subject:"",author:"",keywords:"",creator:""},f={},v=new Pa(f),h=function(a){return a.toFixed(2)},k=function(a){return a.toFixed(3)},U=function(a){return("0"+parseInt(a)).slice(-2)},va=function(a){a="00"+a;return a.substr(a.length-2)},c=function(a){da?m[I].push(a):(P+=a.length+1,ra.push(a))},K=function(){C++;N[C]=P;c(C+" 0 obj");return C},ba=function(a){c("stream");c(a);c("endstream")},Ha=function(){c("/ProcSet [/PDF /Text /ImageB /ImageC /ImageI]");
c("/Font <<");for(var a in r)r.hasOwnProperty(a)&&c("/"+a+" "+r[a].objectNumber+" 0 R");c(">>");c("/Shading <<");for(var b in u)u.hasOwnProperty(b)&&u[b]instanceof f.ShadingPattern&&0<=u[b].objectNumber&&c("/"+b+" "+u[b].objectNumber+" 0 R");v.publish("putShadingPatternDict");c(">>");c("/Pattern <<");for(var g in u)u.hasOwnProperty(g)&&u[g]instanceof f.TilingPattern&&0<=u[g].objectNumber&&c("/"+g+" "+u[g].objectNumber+" 0 R");v.publish("putTilingPatternDict");c(">>");c("/ExtGState <<");for(var d in H)H.hasOwnProperty(d)&&
0<=H[d].objectNumber&&c("/"+d+" "+H[d].objectNumber+" 0 R");v.publish("putGStateDict");c(">>");c("/XObject <<");for(var e in M)M.hasOwnProperty(e)&&0<=M[e].objectNumber&&c("/"+e+" "+M[e].objectNumber+" 0 R");v.publish("putXobjectDict");c(">>")},Ia=function(a,b,g,c){var e="F"+(Object.keys(r).length+1).toString(10);a=r[e]={id:e,PostScriptName:a,fontName:b,fontStyle:g,encoding:c,metadata:{}};G.hasOwnProperty(b)||(G[b]={});G[b][g]=e;v.publish("addFont",a);return e},wa=function(a,b){return new R(a.a*b.a+
a.b*b.c,a.a*b.b+a.b*b.d,a.c*b.a+a.d*b.c,a.c*b.b+a.d*b.d,a.e*b.a+a.f*b.c+b.e,a.e*b.b+a.f*b.d+b.f)},R=function(a,b,g,c,e,l){this.a=a;this.b=b;this.c=g;this.d=c;this.e=e;this.f=l};R.prototype={toString:function(){return[k(this.a),k(this.b),k(this.c),k(this.d),k(this.e),k(this.f)].join(" ")}};var ka=new R(1,0,0,1,0,0),la=function(){this.page=z;this.currentPage=I;this.pages=m.slice(0);this.pagedim=B.slice(0);this.pagesContext=J.slice(0);this.x=ga;this.y=ha;this.matrix=ia;this.width=X;this.height=Q;this.id=
"";this.objectNumber=-1};la.prototype={restore:function(){z=this.page;I=this.currentPage;J=this.pagesContext;B=this.pagedim;m=this.pages;ga=this.x;ha=this.y;ia=this.matrix;X=this.width;Q=this.height}};var xa=function(a,b){if(!pa[a]){var g=(b instanceof f.ShadingPattern?"Sh":"P")+(Object.keys(u).length+1).toString(10);b.id=g;pa[a]=g;u[g]=b;v.publish("addPattern",b)}},Ja=function(a,b){if(!a||!qa[a]){var g=!1,c;for(c in H)if(H.hasOwnProperty(c)&&H[c].equals(b)){g=!0;break}g?b=H[c]:(g="GS"+(Object.keys(H).length+
1).toString(10),H[g]=b,b.id=g);a&&(qa[a]=b.id);v.publish("addGState",b);return b}},ya=function(a,b){var g,c,e,l,f,h;b=b||{};g=b.sourceEncoding||"Unicode";e=b.outputEncoding;if((b.autoencode||e)&&r[D].metadata&&r[D].metadata[g]&&r[D].metadata[g].encoding&&(g=r[D].metadata[g].encoding,!e&&r[D].encoding&&(e=r[D].encoding),!e&&g.codePages&&(e=g.codePages[0]),"string"===typeof e&&(e=g[e]),e)){f=!1;l=[];g=0;for(c=a.length;g<c;g++)(h=e[a.charCodeAt(g)])?l.push(String.fromCharCode(h)):l.push(a[g]),l[g].charCodeAt(0)>>
8&&(f=!0);a=l.join("")}for(g=a.length;void 0===f&&0!==g;)a.charCodeAt(g-1)>>8&&(f=!0),g--;if(f){l=b.noBOM?[]:[254,255];g=0;for(c=a.length;g<c;g++){h=a.charCodeAt(g);f=h>>8;if(f>>8)throw Error("Character at position "+g+" of string '"+a+"' exceeds 16bits. Cannot be encoded into UCS-2 BE");l.push(f);l.push(h-(f<<8))}a=String.fromCharCode.apply(void 0,l)}return a.replace(/\\/g,"\\\\").replace(/\(/g,"\\(").replace(/\)/g,"\\)")},Aa=function(a,b){"string"===typeof b&&b.toLowerCase();if("string"===typeof a){var c=
a.toLowerCase();za.hasOwnProperty(c)&&(a=za[c][0]/E,b=za[c][1]/E)}Array.isArray(a)&&(b=a[1],a=a[0]);da=!0;m[++z]=[];B[z]={width:Number(a)||X,height:Number(b)||Q};J[z]={};Ka(z)},La=function(){Aa.apply(this,arguments);c(h(Qa)+" w");c(ca);0!==sa&&c(sa+" J");0!==ta&&c(ta+" j");v.publish("addPage",{pageNumber:z})},Ra=function(a){0<a&&a<=z&&(m.splice(a,1),B.splice(a,1),z--,I>z&&(I=z),this.setPage(I))},Ka=function(a){0<a&&a<=z&&(I=a,X=B[a].width,Q=B[a].height)},Ba=function(a,b){var c;a=void 0!==a?a:r[D].fontName;
b=void 0!==b?b:r[D].fontStyle;void 0!==a&&(a=a.toLowerCase());switch(a){case "sans-serif":case "verdana":case "arial":case "helvetica":a="helvetica";break;case "fixed":case "monospace":case "terminal":case "courier":a="courier";break;default:a="times"}try{c=G[a][b]}catch(d){}c||(c=G.times[b],null==c&&(c=G.times.normal));return c},Da=function(){da=!1;C=2;ra=[];N=[];W=[];c("%PDF-1.3");var a,b,g,d,e;e=t.adler32cs||q.adler32cs;S&&"undefined"===typeof e&&(S=!1);for(a=1;a<=z;a++){K();g=(X=B[a].width)*E;
b=(Q=B[a].height)*E;c("<</Type /Page");c("/Parent 1 0 R");c("/Resources 2 0 R");c("/MediaBox [0 0 "+h(g)+" "+h(b)+"]");v.publish("putPage",{pageNumber:a,page:m[a]});c("/Contents "+(C+1)+" 0 R");c(">>");c("endobj");b=m[a].join("\n");b=(new R(E,0,0,-E,0,Q)).toString()+" cm\n"+b;K();if(S){g=[];for(d=b.length;d--;)g[d]=b.charCodeAt(d);d=e.from(b);b=new Deflater(6);b.append(new Uint8Array(g));b=b.flush();g=new Uint8Array(b.length+6);g.set(new Uint8Array([120,156]));g.set(b,2);g.set(new Uint8Array([d&255,
d>>8&255,d>>16&255,d>>24&255]),b.length+2);b=String.fromCharCode.apply(null,g);c("<</Length "+b.length+" /Filter [/FlateDecode]>>")}else c("<</Length "+b.length+">>");ba(b);c("endobj")}N[1]=P;c("1 0 obj");c("<</Type /Pages");a="/Kids [";for(d=0;d<z;d++)a+=3+2*d+" 0 R ";c(a+"]");c("/Count "+z);c(">>");c("endobj");v.publish("postPutPages");v.publish("putAdditionalObjects");for(a=0;a<W.length;a++)e=W[a],N[e.objId]=P,c(e.objId+" 0 obj"),c(e.content),c("endobj");C+=W.length;v.publish("postPutAdditionalObjects");
for(var l in r)r.hasOwnProperty(l)&&(a=r[l],a.objectNumber=K(),c("<</BaseFont/"+a.PostScriptName+"/Type/Font"),"string"===typeof a.encoding&&c("/Encoding/"+a.encoding),c("/Subtype/Type1>>"),c("endobj"));for(var y in H)if(H.hasOwnProperty(y)){l=H[y];l.objectNumber=K();c("<<");a=void 0;for(a in l)switch(a){case "opacity":c("/ca "+h(l[a]))}c(">>");c("endobj")}for(var p in M)M.hasOwnProperty(p)&&(y=M[p],y.objectNumber=K(),c("<<"),c("/Type /XObject"),c("/Subtype /Form"),c("/BBox ["+[h(y.x),h(y.y),h(y.x+
y.width),h(y.y+y.height)].join(" ")+"]"),c("/Matrix ["+y.matrix.toString()+"]"),y=y.pages[1].join("\n"),c("/Length "+y.length),c(">>"),ba(y),c("endobj"));for(var n in u)if(u.hasOwnProperty(n))if(u[n]instanceof f.ShadingPattern){p=u[n];y=K();l=p.colors;a=[];for(d=0;1>d;d+=.05)a.push(d);a.push(1);0!=l[0].offset&&l.unshift({offset:0,color:l[0].color});1!=l[l.length-1].offset&&l.push({offset:1,color:l[l.length-1].color});e="";for(b=g=0;b<a.length;b++){for(d=a[b];d>l[g+1].offset;)g++;var Y=l[g].offset;
d=(d-Y)/(l[g+1].offset-Y);var Y=l[g].color,Ca=l[g+1].color;e+=va(Math.round((1-d)*Y[0]+d*Ca[0]).toString(16))+va(Math.round((1-d)*Y[1]+d*Ca[1]).toString(16))+va(Math.round((1-d)*Y[2]+d*Ca[2]).toString(16))}l=e.trim();c("<< /FunctionType 0");c("/Domain [0.0 1.0]");c("/Size [21]");c("/BitsPerSample 8");c("/Range [0.0 1.0 0.0 1.0 0.0 1.0]");c("/Decode [0.0 1.0 0.0 1.0 0.0 1.0]");c("/Length "+l.length);c("/Filter /ASCIIHexDecode");c(">>");ba(l);c("endobj");p.objectNumber=K();c("<< /ShadingType "+p.type);
c("/ColorSpace /DeviceRGB");l="/Coords ["+k(parseFloat(p.coords[0]))+" "+k(parseFloat(p.coords[1]))+" ";l=2===p.type?l+(k(parseFloat(p.coords[2]))+" "+k(parseFloat(p.coords[3]))):l+(k(parseFloat(p.coords[2]))+" "+k(parseFloat(p.coords[3]))+" "+k(parseFloat(p.coords[4]))+" "+k(parseFloat(p.coords[5])));c(l+"]");p.matrix&&c("/Matrix ["+p.matrix.toString()+"]");c("/Function "+y+" 0 R");c("/Extend [true true]");c(">>");c("endobj")}else u[n]instanceof f.TilingPattern&&(p=u[n],y=K(),c("<<"),Ha(),c(">>"),
c("endobj"),p.objectNumber=K(),c("<< /Type /Pattern"),c("/PatternType 1"),c("/PaintType 1"),c("/TilingType 1"),c("/BBox ["+p.boundingBox.map(k).join(" ")+"]"),c("/XStep "+k(p.xStep)),c("/YStep "+k(p.yStep)),c("/Length "+p.stream.length),c("/Resources "+y+" 0 R"),p.matrix&&c("/Matrix ["+p.matrix.toString()+"]"),c(">>"),ba(p.stream),c("endobj"));v.publish("putResources");N[2]=P;c("2 0 obj");c("<<");Ha();c(">>");c("endobj");v.publish("postPutResources");K();c("<<");c("/Producer (jsPDF "+q.version+")");
for(var x in T)T.hasOwnProperty(x)&&T[x]&&c("/"+x.substr(0,1).toUpperCase()+x.substr(1)+" ("+ya(T[x])+")");n=new Date;x=n.getTimezoneOffset();p=Math.abs(x%60);x=[0>x?"+":"-",U(Math.floor(Math.abs(x/60))),"'",U(p),"'"].join("");c(["/CreationDate (D:",n.getFullYear(),U(n.getMonth()+1),U(n.getDate()),U(n.getHours()),U(n.getMinutes()),U(n.getSeconds()),x,")"].join(""));c(">>");c("endobj");K();c("<<");c("/Type /Catalog");c("/Pages 1 0 R");O||(O="fullwidth");switch(O){case "fullwidth":c("/OpenAction [3 0 R /FitH null]");
break;case "fullheight":c("/OpenAction [3 0 R /FitV null]");break;case "fullpage":c("/OpenAction [3 0 R /Fit]");break;case "original":c("/OpenAction [3 0 R /XYZ null null 1]");break;default:n=""+O,"%"===n.substr(n.length-1)&&(O=parseInt(O)/100),"number"===typeof O&&c("/OpenAction [3 0 R /XYZ null null "+h(O)+"]")}ja||(ja="continuous");switch(ja){case "continuous":c("/PageLayout /OneColumn");break;case "single":c("/PageLayout /SinglePage");break;case "two":case "twoleft":c("/PageLayout /TwoColumnLeft");
break;case "tworight":c("/PageLayout /TwoColumnRight")}ua&&c("/PageMode /"+ua);v.publish("putCatalog");c(">>");c("endobj");n=P;c("xref");c("0 "+(C+1));c("0000000000 65535 f ");for(x=1;x<=C;x++)"function"===typeof N[x]?c(("0000000000"+N[x]()).slice(-10)+" 00000 n "):c(("0000000000"+N[x]).slice(-10)+" 00000 n ");c("trailer");c("<<");c("/Size "+(C+1));c("/Root "+C+" 0 R");c("/Info "+(C-1)+" 0 R");c(">>");c("startxref");c(n);c("%%EOF");da=!0;return ra.join("\n")},Ma=function(a){var b="n";if("D"===a)b=
"S";else if("F"===a)b="f";else if("FD"===a||"DF"===a)b="B";else if("f"===a||"f*"===a||"B"===a||"B*"===a)b=a;return b},ma=function(a,b,g){a=Ma(a);if(b){g||(g=ka);var d=pa[b],e=u[d];if(e instanceof f.ShadingPattern)c("q"),c("W "+a),e.gState&&f.setGState(e.gState),c(g.toString()+" cm"),c("/"+d+" sh"),c("Q");else if(e instanceof f.TilingPattern){var l=new R(1,0,0,-1,0,Q);g.matrix&&(l=wa(g.matrix||ka,l),d=e.createClone(b,g.boundingBox,g.xStep,g.yStep,l).id);c("q");c("/Pattern cs");c("/"+d+" scn");e.gState&&
f.setGState(e.gState);c(a);c("Q")}}else c(a)},Na=function(){for(var a=Da(),b=a.length,c=new ArrayBuffer(b),d=new Uint8Array(c);b--;)d[b]=a.charCodeAt(b);return c},Ea=function(){return new Blob([Na()],{type:"application/pdf"})},Oa=function(a){a.foo=function(){try{return a.apply(this,arguments)}catch(c){var b=c.stack||"";~b.indexOf(" at ")&&(b=b.split(" at ")[1]);b="Error in function "+b.split("\n")[0].split("<")[0]+": "+c.message;if(t.console)t.console.error(b,c),t.alert&&alert(b);else throw Error(b);
}};a.foo.bar=a;return a.foo}(function(a,b){var c="dataur"===(""+a).substr(0,6)?"data:application/pdf;base64,"+btoa(Da()):0;switch(a){case void 0:return Da();case "save":if(navigator.getUserMedia&&(void 0===t.URL||void 0===t.URL.createObjectURL))return f.output("dataurlnewwindow");saveAs(Ea(),b);"function"===typeof saveAs.unload&&t.setTimeout&&setTimeout(saveAs.unload,911);break;case "arraybuffer":return Na();case "blob":return Ea();case "bloburi":case "bloburl":return t.URL&&t.URL.createObjectURL(Ea())||
void 0;case "datauristring":case "dataurlstring":return c;case "dataurlnewwindow":if((a=t.open(c))||"undefined"===typeof safari)return a;case "datauri":case "dataurl":return t.document.location.href=c;default:throw Error('Output type "'+a+'" is not supported.');}});switch(A){case "pt":E=1;break;case "mm":E=72/25.4000508;break;case "cm":E=72/2.54000508;break;case "in":E=72;break;case "px":E=96/72;break;case "pc":E=12;break;case "em":E=12;break;case "ex":E=6;break;default:throw"Invalid unit: "+A;}f.internal=
{pdfEscape:ya,getStyle:Ma,getFont:function(){return r[Ba.apply(f,arguments)]},getFontSize:function(){return L},getLineHeight:function(){return L*oa},write:function(a){c(1===arguments.length?a:Array.prototype.join.call(arguments," "))},getCoordinateString:function(a){return h(a)},getVerticalCoordinateString:function(a){return h(a)},collections:{},newObject:K,newAdditionalObject:function(){var a=2*m.length+1,a=a+W.length,a={objId:a,content:""};W.push(a);return a},newObjectDeferred:function(){C++;N[C]=
function(){return P};return C},newObjectDeferredBegin:function(a){N[a]=P},putStream:ba,events:v,scaleFactor:E,pageSize:{get width(){return X},get height(){return Q}},output:function(a,b){return Oa(a,b)},getNumberOfPages:function(){return m.length-1},pages:m,out:c,f2:h,getPageInfo:function(a){return{objId:2*(a-1)+3,pageNumber:a,pageContext:J[a]}},getCurrentPageInfo:function(){return{objId:2*(I-1)+3,pageNumber:I,pageContext:J[I]}},getPDFVersion:function(){return"1.3"}};f.GState=function(a){for(var b in a)a.hasOwnProperty(b)&&
0<="opacity".indexOf(b)&&(this[b]=a[b]);this.id="";this.objectNumber=-1;this.equals=function(a){if(!a||typeof a!==typeof this)return!1;var b=0,c;for(c in this)if(!(0<="id,objectNumber,equals".indexOf(c))){if(this.hasOwnProperty(c)&&!a.hasOwnProperty(c)||this[c]!==a[c])return!1;b++}for(c in a)a.hasOwnProperty(c)&&0>"id,objectNumber,equals".indexOf(c)&&b--;return 0===b}};f.addGState=function(a,b){Ja(a,b);return this};f.addPage=function(){La.apply(this,arguments);return this};f.setPage=function(){Ka.apply(this,
arguments);return this};f.insertPage=function(a){this.addPage();this.movePage(I,a);return this};f.movePage=function(a,b){var c,d,e;if(a>b){e=m[a];d=B[a];for(c=J[a];a>b;a--)m[a]=m[a-1],B[a]=B[a-1],J[a]=J[a-1];m[b]=e;B[b]=d;J[b]=c;this.setPage(b)}else if(a<b){e=m[a];d=B[a];for(c=J[a];a<b;a++)m[a]=m[a+1],B[a]=B[a+1],J[a]=J[a+1];m[b]=e;B[b]=d;J[b]=c;this.setPage(b)}return this};f.deletePage=function(){Ra.apply(this,arguments);return this};f.setDisplayMode=function(a,b,c){O=a;ja=b;ua=c;return this};f.saveGraphicsState=
function(){c("q");Fa.push({key:D,size:L});return this};f.restoreGraphicsState=function(){c("Q");var a=Fa.pop();D=a.key;L=a.size;return this};f.setCurrentTransformationMatrix=function(a){c(a.toString()+" cm");return this};f.beginFormObject=function(a,b,c,d,e){fa.push(new la);z=I=0;m=[];ga=a;ha=b;ia=e;Aa(c,d);return this};f.endFormObject=function(a){if(!ea[a]){var b=new la,c="Xo"+(Object.keys(M).length+1).toString(10);b.id=c;ea[a]=c;M[c]=b;v.publish("addFormObject",b);fa.pop().restore()}return this};
f.doFormObject=function(a,b){a=M[ea[a]];c("q");c(b.toString()+" cm");c("/"+a.id+" Do");c("Q");return this};f.getFormObject=function(a){a=M[ea[a]];return{x:a.x,y:a.y,width:a.width,height:a.height,matrix:a.matrix}};f.Matrix=R;f.matrixMult=wa;f.unitMatrix=ka;f.ShadingPattern=function(a,b,c,d,e){this.type="axial"===a?2:3;this.coords=b;this.colors=c;this.gState=d;this.matrix=e;this.id="";this.objectNumber=-1};f.TilingPattern=function(a,b,c,d,e){this.boundingBox=a;this.xStep=b;this.yStep=c;this.stream=
"";this.cloneIndex=0;this.gState=d;this.matrix=e;this.id="";this.objectNumber=-1};f.TilingPattern.prototype={createClone:function(a,b,c,d,e){b=new f.TilingPattern(b||this.boundingBox,c||this.xStep,d||this.yStep,this.gState,e||this.matrix);b.stream=this.stream;a=a+"$$"+this.cloneIndex++ +"$$";xa(a,b);return b}};f.addShadingPattern=function(a,b){xa(a,b);return this};f.beginTilingPattern=function(a){var b=a.boundingBox[0],c=a.boundingBox[1],d=a.boundingBox[2]-a.boundingBox[0],e=a.boundingBox[3]-a.boundingBox[1];
a=a.matrix;fa.push(new la);z=I=0;m=[];ga=b;ha=c;ia=a;Aa(d,e)};f.endTilingPattern=function(a,b){b.stream=m[I].join("\n");xa(a,b);v.publish("endTilingPattern",b);fa.pop().restore()};f.text=function(a,b,g,d,e,l){function f(a){a=a.split("\t").join(Array(w.TabLen||9).join(" "));return ya(a,d)}if("number"===typeof a){var p=g;g=b;b=a;a=p}"string"===typeof a&&(a=a.match(/[\n\r]/)?a.split(/\r\n|\r|\n/g):[a]);"string"===typeof e&&(l=e,e=null);"string"===typeof d&&(l=d,d=null);"number"===typeof d&&(e=d,d=null);
e&&"number"===typeof e?(e*=Math.PI/180,p=Math.cos(e),e=Math.sin(e),e=new R(p,e,-e,p,0,0)):e||(e=ka);d=d||{};"noBOM"in d||(d.noBOM=!0);"autoencode"in d||(d.autoencode=!0);var p="",n=this.internal.getCurrentPageInfo().pageContext;!0===d.stroke?!0!==n.lastTextWasStroke&&(p="1 Tr\n",n.lastTextWasStroke=!0):(n.lastTextWasStroke&&(p="0 Tr\n"),n.lastTextWasStroke=!1);"undefined"===typeof this._runningPageHeight&&(this._runningPageHeight=0);if("string"===typeof a)a=f(a);else if("[object Array]"===Object.prototype.toString.call(a)){for(var k=
a.concat(),n=[],q=k.length;q--;)n.push(f(k.shift()));if(l){var x,m,v=L*oa,t=a.map(function(a){return this.getStringUnitWidth(a)*L},this);m=Math.max.apply(Math,t);if("center"===l)k=b-m/2,b-=t[0]/2;else if("right"===l)k=b-m,b-=t[0];else throw Error('Unrecognized alignment option, use "center" or "right".');x=b;a=n[0]+") Tj\n";i=1;for(q=n.length;i<q;i++){var u=m-t[i];"center"===l&&(u/=2);a+=k-x+u+" -"+v+" Td ("+n[i];x=k+u;i<q-1&&(a+=") Tj\n")}}else a=n.join(") Tj\nT* (")}else throw Error('Type of text must be string or Array. "'+
a+'" is not recognized.');g=h(g);b=new R(1,0,0,-1,b,g);e=wa(b,e);c("BT\n"+L*oa+" TL\n"+p+(e.toString()+" Tm")+"\n("+a+") Tj\nET");return this};f.lstext=function(a,b,c,d){for(var e=0,l=a.length;e<l;e++,b+=d)this.text(a[e],b,c)};f.line=function(a,b,c,d){return this.lines([[c-a,d-b]],a,b,[1,1],"D")};f.clip=function(){c("W");c("S")};f.lines=function(a,b,g,d,e,l,f,h){var n,q,m,t,u,v,w,r;"number"===typeof a&&(n=g,g=b,b=a,a=n);d=d||[1,1];c(k(b)+" "+k(g)+" m ");n=d[0];d=d[1];q=a.length;r=g;for(g=0;g<q;g++)m=
a[g],2===m.length?(b=m[0]*n+b,r=m[1]*d+r,c(k(b)+" "+k(r)+" l")):(t=m[0]*n+b,u=m[1]*d+r,v=m[2]*n+b,w=m[3]*d+r,b=m[4]*n+b,r=m[5]*d+r,c(k(t)+" "+k(u)+" "+k(v)+" "+k(w)+" "+k(b)+" "+k(r)+" c"));l&&c("h");ma(e,f,h);return this};f.path=function(a,b,g,d){for(var e=0;e<a.length;e++){var f=a[e],h=f.c;switch(f.op){case "m":c(k(h[0])+" "+k(h[1])+" m");break;case "l":c(k(h[0])+" "+k(h[1])+" l");break;case "c":c([k(h[0]),k(h[1]),k(h[2]),k(h[3]),k(h[4]),k(h[5]),"c"].join(" "));break;case "h":c("h")}}ma(b,g,d);
return this};f.rect=function(a,b,g,d,e,f,k){c([h(a),h(b),h(g),h(-d),"re"].join(" "));ma(e,f,k);return this};f.triangle=function(a,b,c,d,e,f,h,k,n){this.lines([[c-a,d-b],[e-c,f-d],[a-e,b-f]],a,b,[1,1],h,!0,k,n);return this};f.roundedRect=function(a,b,c,d,e,f,h,k,n){var m=4/3*(Math.SQRT2-1);e=Math.min(e,.5*c);f=Math.min(f,.5*d);this.lines([[c-2*e,0],[e*m,0,e,f-f*m,e,f],[0,d-2*f],[0,f*m,-(e*m),f,-e,f],[-c+2*e,0],[-(e*m),0,-e,-(f*m),-e,-f],[0,-d+2*f],[0,-(f*m),e*m,-f,e,-f]],a+e,b,[1,1],h,!0,k,n);return this};
f.ellipse=function(a,b,g,d,e,f,k){var m=4/3*(Math.SQRT2-1)*g,n=4/3*(Math.SQRT2-1)*d;c([h(a+g),h(b),"m",h(a+g),h(b-n),h(a+m),h(b-d),h(a),h(b-d),"c"].join(" "));c([h(a-m),h(b-d),h(a-g),h(b-n),h(a-g),h(b),"c"].join(" "));c([h(a-g),h(b+n),h(a-m),h(b+d),h(a),h(b+d),"c"].join(" "));c([h(a+m),h(b+d),h(a+g),h(b+n),h(a+g),h(b),"c"].join(" "));ma(e,f,k);return this};f.circle=function(a,b,c,d,e,f){return this.ellipse(a,b,c,c,d,e,f)};f.setProperties=function(a){for(var b in T)T.hasOwnProperty(b)&&a[b]&&(T[b]=
a[b]);return this};f.setFontSize=function(a){L=a;c("/"+D+" "+L+" Tf");return this};f.getFontSize=function(){return L};f.setFont=function(a,b){D=Ba(a,b);c("/"+D+" "+L+" Tf");return this};f.setFontStyle=f.setFontType=function(a){D=Ba(void 0,a);return this};f.getFontList=function(){var a={},b,c,d;for(b in G)if(G.hasOwnProperty(b))for(c in a[b]=d=[],G[b])G[b].hasOwnProperty(c)&&d.push(c);return a};f.addFont=function(a,b,c){Ia(a,b,c,"StandardEncoding")};f.setLineWidth=function(a){c(a.toFixed(2)+" w");
return this};f.setDrawColor=function(a,b,g,d){a=void 0===b||void 0===d&&a===b===g?"string"===typeof a?a+" G":h(a/255)+" G":void 0===d?"string"===typeof a?[a,b,g,"RG"].join(" "):[h(a/255),h(b/255),h(g/255),"RG"].join(" "):"string"===typeof a?[a,b,g,d,"K"].join(" "):[h(a),h(b),h(g),h(d),"K"].join(" ");c(a);return this};f.setFillColor=function(a,b,g,d){void 0===b||void 0===d&&a===b===g?a="string"===typeof a?a+" g":h(a/255)+" g":void 0===d||"object"===typeof d?(a="string"===typeof a?[a,b,g,"rg"].join(" "):
[h(a/255),h(b/255),h(g/255),"rg"].join(" "),d&&0===d.a&&(a="255 255 255 rg")):a="string"===typeof a?[a,b,g,d,"k"].join(" "):[h(a),h(b),h(g),h(d),"k"].join(" ");c(a);return this};f.setTextColor=function(a,b,g){"string"===typeof a&&/^#[0-9A-Fa-f]{6}$/.test(a)&&(g=parseInt(a.substr(1),16),a=g>>16&255,b=g>>8&255,g&=255);aa=0===a&&0===b&&0===g||"undefined"===typeof b?k(a/255)+" g":[k(a/255),k(b/255),k(g/255),"rg"].join(" ");c(aa);return this};f.setGState=function(a){a="string"===typeof a?H[qa[a]]:Ja(null,
a);a.equals(Ga)||(c("/"+a.id+" gs"),Ga=a)};f.CapJoinStyles={0:0,butt:0,but:0,miter:0,1:1,round:1,rounded:1,circle:1,2:2,projecting:2,project:2,square:2,bevel:2};f.setLineCap=function(a){var b=this.CapJoinStyles[a];if(void 0===b)throw Error("Line cap style of '"+a+"' is not recognized. See or extend .CapJoinStyles property for valid styles");sa=b;c(b+" J");return this};f.setLineJoin=function(a){var b=this.CapJoinStyles[a];if(void 0===b)throw Error("Line join style of '"+a+"' is not recognized. See or extend .CapJoinStyles property for valid styles");
ta=b;c(b+" j");return this};f.setLineMiterLimit=function(a){c(h(a)+" M");return this};f.setLineDashPattern=function(a,b){c(["["+(void 0!==a[0]?a[0]:""),(void 0!==a[1]?a[1]:"")+"]",b,"d"].join(" "));return this};f.output=Oa;f.save=function(a){f.output("save",a)};for(var na in q.API)q.API.hasOwnProperty(na)&&("events"===na&&q.API.events.length?function(a,b){var c,d,e;for(e=b.length-1;-1!==e;e--)c=b[e][0],d=b[e][1],a.subscribe.apply(a,[c].concat("function"===typeof d?[d]:d))}(v,q.API.events):f[na]=q.API[na]);
(function(){for(var a=[["Helvetica","helvetica","normal"],["Helvetica-Bold","helvetica","bold"],["Helvetica-Oblique","helvetica","italic"],["Helvetica-BoldOblique","helvetica","bolditalic"],["Courier","courier","normal"],["Courier-Bold","courier","bold"],["Courier-Oblique","courier","italic"],["Courier-BoldOblique","courier","bolditalic"],["Times-Roman","times","normal"],["Times-Bold","times","bold"],["Times-Italic","times","italic"],["Times-BoldItalic","times","bolditalic"],["ZapfDingbats","zapfdingbats"]],
b=0,c=a.length;b<c;b++){var d=Ia(a[b][0],a[b][1],a[b][2],"StandardEncoding"),e=a[b][0].split("-"),f=e[0],e=e[1]||"";G.hasOwnProperty(f)||(G[f]={});G[f][e]=d}v.publish("addFonts",{fonts:r,dictionary:G})})();D="F1";La(F,V);v.publish("initialized");return f}var za={a0:[2383.94,3370.39],a1:[1683.78,2383.94],a2:[1190.55,1683.78],a3:[841.89,1190.55],a4:[595.28,841.89],a5:[419.53,595.28],a6:[297.64,419.53],a7:[209.76,297.64],a8:[147.4,209.76],a9:[104.88,147.4],a10:[73.7,104.88],b0:[2834.65,4008.19],b1:[2004.09,
2834.65],b2:[1417.32,2004.09],b3:[1000.63,1417.32],b4:[708.66,1000.63],b5:[498.9,708.66],b6:[354.33,498.9],b7:[249.45,354.33],b8:[175.75,249.45],b9:[124.72,175.75],b10:[87.87,124.72],c0:[2599.37,3676.54],c1:[1836.85,2599.37],c2:[1298.27,1836.85],c3:[918.43,1298.27],c4:[649.13,918.43],c5:[459.21,649.13],c6:[323.15,459.21],c7:[229.61,323.15],c8:[161.57,229.61],c9:[113.39,161.57],c10:[79.37,113.39],dl:[311.81,623.62],letter:[612,792],"government-letter":[576,756],legal:[612,1008],"junior-legal":[576,
360],ledger:[1224,792],tabloid:[792,1224],"credit-card":[153,243]};q.API={events:[]};q.version="1.0.0-trunk";"function"===typeof define&&define.amd?define("jsPDF",function(){return q}):"undefined"!==typeof module&&module.exports?module.exports=q:t.jsPDF=q;return q}("undefined"!==typeof self&&self||"undefined"!==typeof window&&window||this);
/base/000_base/node_modules/highcharts/lib/jspdf.src.js
@@ -0,0 +1,3031 @@
/** @preserve
* jsPDF - PDF Document creation from JavaScript
* Version ${versionID}
* CommitID ${commitID}
*
* Copyright (c) 2010-2014 James Hall <james@parall.ax>, https://github.com/MrRio/jsPDF
* 2010 Aaron Spike, https://github.com/acspike
* 2012 Willow Systems Corporation, willow-systems.com
* 2012 Pablo Hess, https://github.com/pablohess
* 2012 Florian Jenett, https://github.com/fjenett
* 2013 Warren Weckesser, https://github.com/warrenweckesser
* 2013 Youssef Beddad, https://github.com/lifof
* 2013 Lee Driscoll, https://github.com/lsdriscoll
* 2013 Stefan Slonevskiy, https://github.com/stefslon
* 2013 Jeremy Morel, https://github.com/jmorel
* 2013 Christoph Hartmann, https://github.com/chris-rock
* 2014 Juan Pablo Gaviria, https://github.com/juanpgaviria
* 2014 James Makes, https://github.com/dollaruw
* 2014 Diego Casorran, https://github.com/diegocr
* 2014 Steven Spungin, https://github.com/Flamenco
* 2014 Kenneth Glassey, https://github.com/Gavvers
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
* Contributor(s):
* siefkenj, ahwolf, rickygu, Midnith, saintclair, eaparango,
* kim3er, mfo, alnorth, Flamenco
*/
 
/**
* Creates new jsPDF document object instance.
*
* @class
* @param orientation One of "portrait" or "landscape" (or shortcuts "p" (Default), "l")
* @param unit Measurement unit to be used when coordinates are specified.
* One of "pt" (points), "mm" (Default), "cm", "in"
* @param format One of 'pageFormats' as shown below, default: a4
* @returns {jsPDF}
* @name jsPDF
*/
var jsPDF = (function(global) {
'use strict';
var pdfVersion = '1.3',
pageFormats = { // Size in pt of various paper formats
'a0' : [2383.94, 3370.39], 'a1' : [1683.78, 2383.94],
'a2' : [1190.55, 1683.78], 'a3' : [ 841.89, 1190.55],
'a4' : [ 595.28, 841.89], 'a5' : [ 419.53, 595.28],
'a6' : [ 297.64, 419.53], 'a7' : [ 209.76, 297.64],
'a8' : [ 147.40, 209.76], 'a9' : [ 104.88, 147.40],
'a10' : [ 73.70, 104.88], 'b0' : [2834.65, 4008.19],
'b1' : [2004.09, 2834.65], 'b2' : [1417.32, 2004.09],
'b3' : [1000.63, 1417.32], 'b4' : [ 708.66, 1000.63],
'b5' : [ 498.90, 708.66], 'b6' : [ 354.33, 498.90],
'b7' : [ 249.45, 354.33], 'b8' : [ 175.75, 249.45],
'b9' : [ 124.72, 175.75], 'b10' : [ 87.87, 124.72],
'c0' : [2599.37, 3676.54], 'c1' : [1836.85, 2599.37],
'c2' : [1298.27, 1836.85], 'c3' : [ 918.43, 1298.27],
'c4' : [ 649.13, 918.43], 'c5' : [ 459.21, 649.13],
'c6' : [ 323.15, 459.21], 'c7' : [ 229.61, 323.15],
'c8' : [ 161.57, 229.61], 'c9' : [ 113.39, 161.57],
'c10' : [ 79.37, 113.39], 'dl' : [ 311.81, 623.62],
'letter' : [612, 792],
'government-letter' : [576, 756],
'legal' : [612, 1008],
'junior-legal' : [576, 360],
'ledger' : [1224, 792],
'tabloid' : [792, 1224],
'credit-card' : [153, 243]
};
 
/**
* jsPDF's Internal PubSub Implementation.
* See mrrio.github.io/jsPDF/doc/symbols/PubSub.html
* Backward compatible rewritten on 2014 by
* Diego Casorran, https://github.com/diegocr
*
* @class
* @name PubSub
*/
function PubSub(context) {
var topics = {};
 
this.subscribe = function(topic, callback, once) {
if(typeof callback !== 'function') {
return false;
}
 
if(!topics.hasOwnProperty(topic)) {
topics[topic] = {};
}
 
var id = Math.random().toString(35);
topics[topic][id] = [callback,!!once];
 
return id;
};
 
this.unsubscribe = function(token) {
for(var topic in topics) {
if(topics[topic][token]) {
delete topics[topic][token];
return true;
}
}
return false;
};
 
this.publish = function(topic) {
if(topics.hasOwnProperty(topic)) {
var args = Array.prototype.slice.call(arguments, 1), idr = [];
 
for(var id in topics[topic]) {
var sub = topics[topic][id];
try {
sub[0].apply(context, args);
} catch(ex) {
if(global.console) {
console.error('jsPDF PubSub Error', ex.message, ex);
}
}
if(sub[1]) idr.push(id);
}
if(idr.length) idr.forEach(this.unsubscribe);
}
};
}
 
/**
* @constructor
* @private
*/
function jsPDF(orientation, unit, format, compressPdf) {
var options = {};
 
if (typeof orientation === 'object') {
options = orientation;
 
orientation = options.orientation;
unit = options.unit || unit;
format = options.format || format;
compressPdf = options.compress || options.compressPdf || compressPdf;
}
 
// Default options
unit = unit || 'mm';
format = format || 'a4';
orientation = ('' + (orientation || 'P')).toLowerCase();
 
var format_as_string = ('' + format).toLowerCase(),
compress = !!compressPdf && typeof Uint8Array === 'function',
textColor = options.textColor || '0 g',
drawColor = options.drawColor || '0 G',
activeFontSize = options.fontSize || 16,
lineHeightProportion = options.lineHeight || 1.15,
lineWidth = options.lineWidth || 0.200025, // 2mm
objectNumber = 2, // 'n' Current object number
outToPages = !1, // switches where out() prints. outToPages true = push to pages obj. outToPages false = doc builder content
offsets = [], // List of offsets. Activated and reset by buildDocument(). Pupulated by various calls buildDocument makes.
fonts = {}, // collection of font objects, where key is fontKey - a dynamically created label for a given font.
fontmap = {}, // mapping structure fontName > fontStyle > font key - performance layer. See addFont()
activeFontKey, // will be string representing the KEY of the font as combination of fontName + fontStyle
 
fontStateStack = [], //
 
patterns = {}, // collection of pattern objects
patternMap = {}, // see fonts
 
gStates = {}, // collection of graphic state objects
gStatesMap = {}, // see fonts
activeGState = null,
 
k, // Scale factor
tmp,
page = 0,
currentPage,
pages = [],
pagesContext = [], // same index as pages and pagedim
pagedim = [],
content = [],
additionalObjects = [],
lineCapID = 0,
lineJoinID = 0,
content_length = 0,
 
renderTargets = {},
renderTargetMap = {},
renderTargetStack = [],
 
pageX, pageY, pageMatrix, // only used for FormObjects
pageWidth,
pageHeight,
pageMode,
zoomMode,
layoutMode,
documentProperties = {
'title' : '',
'subject' : '',
'author' : '',
'keywords' : '',
'creator' : ''
},
API = {},
events = new PubSub(API),
 
/////////////////////
// Private functions
/////////////////////
f2 = function(number) {
return number.toFixed(2); // Ie, %.2f
},
f3 = function(number) {
return number.toFixed(3); // Ie, %.3f
},
padd2 = function(number) {
return ('0' + parseInt(number)).slice(-2);
},
padd2Hex = function (hexString) {
var s = "00" + hexString;
return s.substr(s.length - 2);
},
out = function(string) {
if (outToPages) {
/* set by beginPage */
pages[currentPage].push(string);
} else {
// +1 for '\n' that will be used to join 'content'
content_length += string.length + 1;
content.push(string);
}
},
newObject = function() {
// Begin a new object
objectNumber++;
offsets[objectNumber] = content_length;
out(objectNumber + ' 0 obj');
return objectNumber;
},
// Does not output the object until after the pages have been output.
// Returns an object containing the objectId and content.
// All pages have been added so the object ID can be estimated to start right after.
// This does not modify the current objectNumber; It must be updated after the newObjects are output.
newAdditionalObject = function() {
var objId = pages.length * 2 + 1;
objId += additionalObjects.length;
var obj = {objId:objId, content:''};
additionalObjects.push(obj);
return obj;
},
// Does not output the object. The caller must call newObjectDeferredBegin(oid) before outputing any data
newObjectDeferred = function() {
objectNumber++;
offsets[objectNumber] = function(){
return content_length;
};
return objectNumber;
},
newObjectDeferredBegin = function(oid) {
offsets[oid] = content_length;
},
putStream = function(str) {
out('stream');
out(str);
out('endstream');
},
putPages = function() {
var n,p,arr,i,deflater,adler32,adler32cs,wPt,hPt;
 
adler32cs = global.adler32cs || jsPDF.adler32cs;
if (compress && typeof adler32cs === 'undefined') {
compress = false;
}
 
// outToPages = false as set in endDocument(). out() writes to content.
 
for (n = 1; n <= page; n++) {
newObject();
wPt = (pageWidth = pagedim[n].width) * k;
hPt = (pageHeight = pagedim[n].height) * k;
out('<</Type /Page');
out('/Parent 1 0 R');
out('/Resources 2 0 R');
out('/MediaBox [0 0 ' + f2(wPt) + ' ' + f2(hPt) + ']');
// Added for annotation plugin
events.publish('putPage', {pageNumber: n, page: pages[n]});
out('/Contents ' + (objectNumber + 1) + ' 0 R');
out('>>');
out('endobj');
 
// Page content
p = pages[n].join('\n');
 
// prepend global change of basis matrix
// (Now, instead of converting every coordinate to the pdf coordinate system, we apply a matrix
// that does this job for us (however, texts, images and similar objects must be drawn bottom up))
p = new Matrix(k, 0, 0, -k, 0, pageHeight).toString() + " cm\n" + p;
 
newObject();
if (compress) {
arr = [];
i = p.length;
while(i--) {
arr[i] = p.charCodeAt(i);
}
adler32 = adler32cs.from(p);
deflater = new Deflater(6);
deflater.append(new Uint8Array(arr));
p = deflater.flush();
arr = new Uint8Array(p.length + 6);
arr.set(new Uint8Array([120, 156]));
arr.set(p, 2);
arr.set(new Uint8Array([adler32 & 0xFF, (adler32 >> 8) & 0xFF, (adler32 >> 16) & 0xFF, (adler32 >> 24) & 0xFF]), p.length+2);
p = String.fromCharCode.apply(null, arr);
out('<</Length ' + p.length + ' /Filter [/FlateDecode]>>');
} else {
out('<</Length ' + p.length + '>>');
}
putStream(p);
out('endobj');
}
offsets[1] = content_length;
out('1 0 obj');
out('<</Type /Pages');
var kids = '/Kids [';
for (i = 0; i < page; i++) {
kids += (3 + 2 * i) + ' 0 R ';
}
out(kids + ']');
out('/Count ' + page);
out('>>');
out('endobj');
events.publish('postPutPages');
},
putFont = function(font) {
font.objectNumber = newObject();
out('<</BaseFont/' + font.PostScriptName + '/Type/Font');
if (typeof font.encoding === 'string') {
out('/Encoding/' + font.encoding);
}
out('/Subtype/Type1>>');
out('endobj');
},
putFonts = function() {
for (var fontKey in fonts) {
if (fonts.hasOwnProperty(fontKey)) {
putFont(fonts[fontKey]);
}
}
},
putXObject = function (xObject) {
xObject.objectNumber = newObject();
out("<<");
out("/Type /XObject");
out("/Subtype /Form");
out("/BBox [" + [
f2(xObject.x),
f2(xObject.y),
f2(xObject.x + xObject.width),
f2(xObject.y + xObject.height)
].join(" ") + "]");
out("/Matrix [" + xObject.matrix.toString() + "]");
// TODO: /Resources
 
var p = xObject.pages[1].join("\n");
out("/Length " + p.length);
 
out(">>");
putStream(p);
out("endobj");
},
putXObjects = function () {
for (var xObjectKey in renderTargets) {
if (renderTargets.hasOwnProperty(xObjectKey)) {
putXObject(renderTargets[xObjectKey]);
}
}
},
 
interpolateAndEncodeRGBStream = function (colors, numberSamples) {
var tValues = [];
var t;
var dT = 1.0 / (numberSamples - 1);
for (t = 0.0; t < 1.0; t += dT) {
tValues.push(t);
}
tValues.push(1.0);
 
// add first and last control point if not present
if (colors[0].offset != 0.0) {
var c0 = {
offset: 0.0,
color: colors[0].color
};
colors.unshift(c0)
}
if (colors[colors.length - 1].offset != 1.0) {
var c1 = {
offset: 1.0,
color: colors[colors.length - 1].color
};
colors.push(c1);
}
 
var out = "";
var index = 0;
 
for (var i = 0; i < tValues.length; i++) {
t = tValues[i];
 
while (t > colors[index + 1].offset)
index++;
 
var a = colors[index].offset;
var b = colors[index + 1].offset;
var d = (t - a) / (b - a);
 
var aColor = colors[index].color;
var bColor = colors[index + 1].color;
 
out += padd2Hex((Math.round((1 - d) * aColor[0] + d * bColor[0])).toString(16))
+ padd2Hex((Math.round((1 - d) * aColor[1] + d * bColor[1])).toString(16))
+ padd2Hex((Math.round((1 - d) * aColor[2] + d * bColor[2])).toString(16));
}
return out.trim();
},
putShadingPattern = function (pattern, numberSamples) {
/*
Axial patterns shade between the two points specified in coords, radial patterns between the inner
and outer circle.
 
The user can specify an array (colors) that maps t-Values in [0, 1] to RGB colors. These are now
interpolated to equidistant samples and written to pdf as a sample (type 0) function.
*/
 
// The number of color samples that should be used to describe the shading.
// The higher, the more accurate the gradient will be.
numberSamples || (numberSamples = 21);
 
var funcObjectNumber = newObject();
var stream = interpolateAndEncodeRGBStream(pattern.colors, numberSamples);
out("<< /FunctionType 0");
out("/Domain [0.0 1.0]");
out("/Size [" + numberSamples + "]");
out("/BitsPerSample 8");
out("/Range [0.0 1.0 0.0 1.0 0.0 1.0]");
out("/Decode [0.0 1.0 0.0 1.0 0.0 1.0]");
out("/Length " + stream.length);
// The stream is Hex encoded
out("/Filter /ASCIIHexDecode");
out(">>");
putStream(stream);
out("endobj");
 
pattern.objectNumber = newObject();
out("<< /ShadingType " + pattern.type);
out("/ColorSpace /DeviceRGB");
 
var coords = "/Coords ["
+ f3(parseFloat(pattern.coords[0])) + " "// x1
+ f3(parseFloat(pattern.coords[1])) + " "; // y1
if (pattern.type === 2) {
// axial
coords += f3(parseFloat(pattern.coords[2])) + " " // x2
+ f3(parseFloat(pattern.coords[3])); // y2
} else {
// radial
coords += f3(parseFloat(pattern.coords[2])) + " "// r1
+ f3(parseFloat(pattern.coords[3])) + " " // x2
+ f3(parseFloat(pattern.coords[4])) + " " // y2
+ f3(parseFloat(pattern.coords[5])); // r2
}
coords += "]";
out(coords);
 
if (pattern.matrix) {
out("/Matrix [" + pattern.matrix.toString() + "]");
}
 
out("/Function " + funcObjectNumber + " 0 R");
out("/Extend [true true]");
out(">>");
out("endobj");
},
putTilingPattern = function (pattern) {
var resourcesObjectNumber = newObject();
out("<<");
putResourceDictionary();
out(">>");
out("endobj");
 
pattern.objectNumber = newObject();
out("<< /Type /Pattern");
out("/PatternType 1"); // tiling pattern
out("/PaintType 1"); // colored tiling pattern
out("/TilingType 1"); // constant spacing
out("/BBox [" + pattern.boundingBox.map(f3).join(" ") + "]");
out("/XStep " + f3(pattern.xStep));
out("/YStep " + f3(pattern.yStep));
out("/Length " + pattern.stream.length);
out("/Resources " + resourcesObjectNumber + " 0 R"); // TODO: resources
pattern.matrix && out("/Matrix [" + pattern.matrix.toString() + "]");
 
out(">>");
 
putStream(pattern.stream);
 
out("endobj");
},
putPatterns = function () {
var patternKey;
for (patternKey in patterns) {
if (patterns.hasOwnProperty(patternKey)) {
if (patterns[patternKey] instanceof API.ShadingPattern) {
putShadingPattern(patterns[patternKey]);
} else if (patterns[patternKey] instanceof API.TilingPattern) {
putTilingPattern(patterns[patternKey]);
}
}
}
},
 
putGState = function (gState) {
gState.objectNumber = newObject();
out("<<");
for (var p in gState) {
switch (p) {
case "opacity":
out("/ca " + f2(gState[p]));
break;
}
}
out(">>");
out("endobj");
},
putGStates = function () {
var gStateKey;
for (gStateKey in gStates) {
if (gStates.hasOwnProperty(gStateKey)) {
putGState(gStates[gStateKey]);
}
}
},
 
putXobjectDict = function () {
for (var xObjectKey in renderTargets) {
if (renderTargets.hasOwnProperty(xObjectKey) && renderTargets[xObjectKey].objectNumber >= 0) {
out("/" + xObjectKey + " " + renderTargets[xObjectKey].objectNumber + " 0 R");
}
}
 
events.publish('putXobjectDict');
},
 
putShadingPatternDict = function () {
for (var patternKey in patterns) {
if (patterns.hasOwnProperty(patternKey) && patterns[patternKey] instanceof API.ShadingPattern && patterns[patternKey].objectNumber >= 0) {
out("/" + patternKey + " " + patterns[patternKey].objectNumber + " 0 R");
}
}
 
events.publish("putShadingPatternDict");
},
 
putTilingPatternDict = function () {
for (var patternKey in patterns) {
if (patterns.hasOwnProperty(patternKey) && patterns[patternKey] instanceof API.TilingPattern && patterns[patternKey].objectNumber >= 0) {
out("/" + patternKey + " " + patterns[patternKey].objectNumber + " 0 R");
}
}
 
events.publish("putTilingPatternDict");
},
 
putGStatesDict = function () {
var gStateKey;
for (gStateKey in gStates) {
if (gStates.hasOwnProperty(gStateKey) && gStates[gStateKey].objectNumber >= 0) {
out("/" + gStateKey + " " + gStates[gStateKey].objectNumber + " 0 R");
}
}
 
events.publish("putGStateDict");
},
putResourceDictionary = function() {
out('/ProcSet [/PDF /Text /ImageB /ImageC /ImageI]');
out('/Font <<');
// Do this for each font, the '1' bit is the index of the font
for (var fontKey in fonts) {
if (fonts.hasOwnProperty(fontKey)) {
out('/' + fontKey + ' ' + fonts[fontKey].objectNumber + ' 0 R');
}
}
out('>>');
 
out("/Shading <<");
putShadingPatternDict();
out(">>");
 
out("/Pattern <<");
putTilingPatternDict();
out(">>");
 
out("/ExtGState <<");
putGStatesDict();
out('>>');
 
out('/XObject <<');
putXobjectDict();
out('>>');
},
putResources = function() {
putFonts();
putGStates();
putXObjects();
putPatterns();
events.publish('putResources');
// Resource dictionary
offsets[2] = content_length;
out('2 0 obj');
out('<<');
putResourceDictionary();
out('>>');
out('endobj');
events.publish('postPutResources');
},
putAdditionalObjects = function() {
events.publish('putAdditionalObjects');
for (var i=0; i<additionalObjects.length; i++){
var obj = additionalObjects[i];
offsets[obj.objId] = content_length;
out( obj.objId + ' 0 obj');
out(obj.content);
out('endobj');
}
objectNumber += additionalObjects.length;
events.publish('postPutAdditionalObjects');
},
addToFontDictionary = function(fontKey, fontName, fontStyle) {
// this is mapping structure for quick font key lookup.
// returns the KEY of the font (ex: "F1") for a given
// pair of font name and type (ex: "Arial". "Italic")
if (!fontmap.hasOwnProperty(fontName)) {
fontmap[fontName] = {};
}
fontmap[fontName][fontStyle] = fontKey;
},
/**
* FontObject describes a particular font as member of an instnace of jsPDF
*
* It's a collection of properties like 'id' (to be used in PDF stream),
* 'fontName' (font's family name), 'fontStyle' (font's style variant label)
*
* @public
* @property id {String} PDF-document-instance-specific label assinged to the font.
* @property PostScriptName {String} PDF specification full name for the font
* @property encoding {Object} Encoding_name-to-Font_metrics_object mapping.
* @name FontObject
*/
addFont = function(PostScriptName, fontName, fontStyle, encoding) {
var fontKey = 'F' + (Object.keys(fonts).length + 1).toString(10),
// This is FontObject
font = fonts[fontKey] = {
'id' : fontKey,
'PostScriptName' : PostScriptName,
'fontName' : fontName,
'fontStyle' : fontStyle,
'encoding' : encoding,
'metadata' : {}
};
addToFontDictionary(fontKey, fontName, fontStyle);
events.publish('addFont', font);
 
return fontKey;
},
addFonts = function() {
 
var HELVETICA = "helvetica",
TIMES = "times",
COURIER = "courier",
NORMAL = "normal",
BOLD = "bold",
ITALIC = "italic",
BOLD_ITALIC = "bolditalic",
encoding = 'StandardEncoding',
ZAPF = "zapfdingbats",
standardFonts = [
['Helvetica', HELVETICA, NORMAL],
['Helvetica-Bold', HELVETICA, BOLD],
['Helvetica-Oblique', HELVETICA, ITALIC],
['Helvetica-BoldOblique', HELVETICA, BOLD_ITALIC],
['Courier', COURIER, NORMAL],
['Courier-Bold', COURIER, BOLD],
['Courier-Oblique', COURIER, ITALIC],
['Courier-BoldOblique', COURIER, BOLD_ITALIC],
['Times-Roman', TIMES, NORMAL],
['Times-Bold', TIMES, BOLD],
['Times-Italic', TIMES, ITALIC],
['Times-BoldItalic', TIMES, BOLD_ITALIC],
['ZapfDingbats',ZAPF ]
];
 
for (var i = 0, l = standardFonts.length; i < l; i++) {
var fontKey = addFont(
standardFonts[i][0],
standardFonts[i][1],
standardFonts[i][2],
encoding);
 
// adding aliases for standard fonts, this time matching the capitalization
var parts = standardFonts[i][0].split('-');
addToFontDictionary(fontKey, parts[0], parts[1] || '');
}
events.publish('addFonts', { fonts : fonts, dictionary : fontmap });
},
matrixMult = function (m1, m2) {
return new Matrix(
m1.a * m2.a + m1.b * m2.c,
m1.a * m2.b + m1.b * m2.d,
m1.c * m2.a + m1.d * m2.c,
m1.c * m2.b + m1.d * m2.d,
m1.e * m2.a + m1.f * m2.c + m2.e,
m1.e * m2.b + m1.f * m2.d + m2.f
);
},
Matrix = function (a, b, c, d, e, f) {
this.a = a;
this.b = b;
this.c = c;
this.d = d;
this.e = e;
this.f = f;
};
 
Matrix.prototype = {
toString: function () {
return [
f3(this.a),
f3(this.b),
f3(this.c),
f3(this.d),
f3(this.e),
f3(this.f)
].join(" ");
}
};
 
var unitMatrix = new Matrix(1, 0, 0, 1, 0, 0),
 
// Used (1) to save the current stream state to the XObjects stack and (2) to save completed form
// objects in the xObjects map.
RenderTarget = function () {
this.page = page;
this.currentPage = currentPage;
this.pages = pages.slice(0);
this.pagedim = pagedim.slice(0);
this.pagesContext = pagesContext.slice(0);
this.x = pageX;
this.y = pageY;
this.matrix = pageMatrix;
this.width = pageWidth;
this.height = pageHeight;
 
this.id = ""; // set by endFormObject()
this.objectNumber = -1; // will be set by putXObject()
};
 
RenderTarget.prototype = {
restore: function () {
page = this.page;
currentPage = this.currentPage;
pagesContext = this.pagesContext;
pagedim = this.pagedim;
pages = this.pages;
pageX = this.x;
pageY = this.y;
pageMatrix = this.matrix;
pageWidth = this.width;
pageHeight = this.height;
}
};
 
var beginNewRenderTarget = function (x, y, width, height, matrix) {
// save current state
renderTargetStack.push(new RenderTarget());
 
// clear pages
page = currentPage = 0;
pages = [];
pageX = x;
pageY = y;
 
pageMatrix = matrix;
 
beginPage(width, height);
},
 
endFormObject = function (key) {
// only add it if it is not already present (the keys provided by the user must be unique!)
if (renderTargetMap[key])
return;
 
// save the created xObject
var newXObject = new RenderTarget();
 
var xObjectId = 'Xo' + (Object.keys(renderTargets).length + 1).toString(10);
newXObject.id = xObjectId;
 
renderTargetMap[key] = xObjectId;
renderTargets[xObjectId] = newXObject;
 
events.publish('addFormObject', newXObject);
 
// restore state from stack
renderTargetStack.pop().restore();
},
 
/**
* Adds a new pattern for later use.
* @param {String} key The key by it can be referenced later. The keys must be unique!
* @param {API.Pattern} pattern The pattern
*/
addPattern = function (key, pattern) {
// only add it if it is not already present (the keys provided by the user must be unique!)
if (patternMap[key])
return;
 
var prefix = pattern instanceof API.ShadingPattern ? "Sh" : "P";
var patternKey = prefix + (Object.keys(patterns).length + 1).toString(10);
pattern.id = patternKey;
 
patternMap[key] = patternKey;
patterns[patternKey] = pattern;
 
events.publish('addPattern', pattern);
},
 
/**
* Adds a new Graphics State. Duplicates are automatically eliminated.
* @param {String} key Might also be null, if no later reference to this gState is needed
* @param {Object} gState The gState object
*/
addGState = function (key, gState) {
// only add it if it is not already present (the keys provided by the user must be unique!)
if (key && gStatesMap[key])
return;
 
var duplicate = false;
for (var s in gStates) {
if (gStates.hasOwnProperty(s)) {
if (gStates[s].equals(gState)) {
duplicate = true;
break;
}
}
}
 
if (duplicate) {
gState = gStates[s];
} else {
var gStateKey = 'GS' + (Object.keys(gStates).length + 1).toString(10);
gStates[gStateKey] = gState;
gState.id = gStateKey;
}
 
// several user keys may point to the same GState object
key && (gStatesMap[key] = gState.id);
 
events.publish('addGState', gState);
 
return gState;
},
SAFE = function __safeCall(fn) {
fn.foo = function __safeCallWrapper() {
try {
return fn.apply(this, arguments);
} catch (e) {
var stack = e.stack || '';
if(~stack.indexOf(' at ')) stack = stack.split(" at ")[1];
var m = "Error in function " + stack.split("\n")[0].split('<')[0] + ": " + e.message;
if(global.console) {
global.console.error(m, e);
if(global.alert) alert(m);
} else {
throw new Error(m);
}
}
};
fn.foo.bar = fn;
return fn.foo;
},
to8bitStream = function(text, flags) {
/**
* PDF 1.3 spec:
* "For text strings encoded in Unicode, the first two bytes must be 254 followed by
* 255, representing the Unicode byte order marker, U+FEFF. (This sequence conflicts
* with the PDFDocEncoding character sequence thorn ydieresis, which is unlikely
* to be a meaningful beginning of a word or phrase.) The remainder of the
* string consists of Unicode character codes, according to the UTF-16 encoding
* specified in the Unicode standard, version 2.0. Commonly used Unicode values
* are represented as 2 bytes per character, with the high-order byte appearing first
* in the string."
*
* In other words, if there are chars in a string with char code above 255, we
* recode the string to UCS2 BE - string doubles in length and BOM is prepended.
*
* HOWEVER!
* Actual *content* (body) text (as opposed to strings used in document properties etc)
* does NOT expect BOM. There, it is treated as a literal GID (Glyph ID)
*
* Because of Adobe's focus on "you subset your fonts!" you are not supposed to have
* a font that maps directly Unicode (UCS2 / UTF16BE) code to font GID, but you could
* fudge it with "Identity-H" encoding and custom CIDtoGID map that mimics Unicode
* code page. There, however, all characters in the stream are treated as GIDs,
* including BOM, which is the reason we need to skip BOM in content text (i.e. that
* that is tied to a font).
*
* To signal this "special" PDFEscape / to8bitStream handling mode,
* API.text() function sets (unless you overwrite it with manual values
* given to API.text(.., flags) )
* flags.autoencode = true
* flags.noBOM = true
*
* ===================================================================================
* `flags` properties relied upon:
* .sourceEncoding = string with encoding label.
* "Unicode" by default. = encoding of the incoming text.
* pass some non-existing encoding name
* (ex: 'Do not touch my strings! I know what I am doing.')
* to make encoding code skip the encoding step.
* .outputEncoding = Either valid PDF encoding name
* (must be supported by jsPDF font metrics, otherwise no encoding)
* or a JS object, where key = sourceCharCode, value = outputCharCode
* missing keys will be treated as: sourceCharCode === outputCharCode
* .noBOM
* See comment higher above for explanation for why this is important
* .autoencode
* See comment higher above for explanation for why this is important
*/
 
var i,l,sourceEncoding,encodingBlock,outputEncoding,newtext,isUnicode,ch,bch;
 
flags = flags || {};
sourceEncoding = flags.sourceEncoding || 'Unicode';
outputEncoding = flags.outputEncoding;
 
// This 'encoding' section relies on font metrics format
// attached to font objects by, among others,
// "Willow Systems' standard_font_metrics plugin"
// see jspdf.plugin.standard_font_metrics.js for format
// of the font.metadata.encoding Object.
// It should be something like
// .encoding = {'codePages':['WinANSI....'], 'WinANSI...':{code:code, ...}}
// .widths = {0:width, code:width, ..., 'fof':divisor}
// .kerning = {code:{previous_char_code:shift, ..., 'fof':-divisor},...}
if ((flags.autoencode || outputEncoding) &&
fonts[activeFontKey].metadata &&
fonts[activeFontKey].metadata[sourceEncoding] &&
fonts[activeFontKey].metadata[sourceEncoding].encoding) {
encodingBlock = fonts[activeFontKey].metadata[sourceEncoding].encoding;
 
// each font has default encoding. Some have it clearly defined.
if (!outputEncoding && fonts[activeFontKey].encoding) {
outputEncoding = fonts[activeFontKey].encoding;
}
 
// Hmmm, the above did not work? Let's try again, in different place.
if (!outputEncoding && encodingBlock.codePages) {
outputEncoding = encodingBlock.codePages[0]; // let's say, first one is the default
}
 
if (typeof outputEncoding === 'string') {
outputEncoding = encodingBlock[outputEncoding];
}
// we want output encoding to be a JS Object, where
// key = sourceEncoding's character code and
// value = outputEncoding's character code.
if (outputEncoding) {
isUnicode = false;
newtext = [];
for (i = 0, l = text.length; i < l; i++) {
ch = outputEncoding[text.charCodeAt(i)];
if (ch) {
newtext.push(
String.fromCharCode(ch));
} else {
newtext.push(
text[i]);
}
 
// since we are looping over chars anyway, might as well
// check for residual unicodeness
if (newtext[i].charCodeAt(0) >> 8) {
/* more than 255 */
isUnicode = true;
}
}
text = newtext.join('');
}
}
 
i = text.length;
// isUnicode may be set to false above. Hence the triple-equal to undefined
while (isUnicode === undefined && i !== 0) {
if (text.charCodeAt(i - 1) >> 8) {
/* more than 255 */
isUnicode = true;
}
i--;
}
if (!isUnicode) {
return text;
}
 
newtext = flags.noBOM ? [] : [254, 255];
for (i = 0, l = text.length; i < l; i++) {
ch = text.charCodeAt(i);
bch = ch >> 8; // divide by 256
if (bch >> 8) {
/* something left after dividing by 256 second time */
throw new Error("Character at position " + i + " of string '"
+ text + "' exceeds 16bits. Cannot be encoded into UCS-2 BE");
}
newtext.push(bch);
newtext.push(ch - (bch << 8));
}
return String.fromCharCode.apply(undefined, newtext);
},
pdfEscape = function(text, flags) {
/**
* Replace '/', '(', and ')' with pdf-safe versions
*
* Doing to8bitStream does NOT make this PDF display unicode text. For that
* we also need to reference a unicode font and embed it - royal pain in the rear.
*
* There is still a benefit to to8bitStream - PDF simply cannot handle 16bit chars,
* which JavaScript Strings are happy to provide. So, while we still cannot display
* 2-byte characters property, at least CONDITIONALLY converting (entire string containing)
* 16bit chars to (USC-2-BE) 2-bytes per char + BOM streams we ensure that entire PDF
* is still parseable.
* This will allow immediate support for unicode in document properties strings.
*/
return to8bitStream(text, flags).replace(/\\/g, '\\\\').replace(/\(/g, '\\(').replace(/\)/g, '\\)');
},
putInfo = function() {
out('/Producer (jsPDF ' + jsPDF.version + ')');
for(var key in documentProperties) {
if(documentProperties.hasOwnProperty(key) && documentProperties[key]) {
out('/'+key.substr(0,1).toUpperCase() + key.substr(1)
+' (' + pdfEscape(documentProperties[key]) + ')');
}
}
var created = new Date(),
tzoffset = created.getTimezoneOffset(),
tzsign = tzoffset < 0 ? '+' : '-',
tzhour = Math.floor(Math.abs(tzoffset / 60)),
tzmin = Math.abs(tzoffset % 60),
tzstr = [tzsign, padd2(tzhour), "'", padd2(tzmin), "'"].join('');
out(['/CreationDate (D:',
created.getFullYear(),
padd2(created.getMonth() + 1),
padd2(created.getDate()),
padd2(created.getHours()),
padd2(created.getMinutes()),
padd2(created.getSeconds()), tzstr, ')'].join(''));
},
putCatalog = function() {
out('/Type /Catalog');
out('/Pages 1 0 R');
// PDF13ref Section 7.2.1
if (!zoomMode) zoomMode = 'fullwidth';
switch(zoomMode) {
case 'fullwidth' : out('/OpenAction [3 0 R /FitH null]'); break;
case 'fullheight' : out('/OpenAction [3 0 R /FitV null]'); break;
case 'fullpage' : out('/OpenAction [3 0 R /Fit]'); break;
case 'original' : out('/OpenAction [3 0 R /XYZ null null 1]'); break;
default:
var pcn = '' + zoomMode;
if (pcn.substr(pcn.length-1) === '%')
zoomMode = parseInt(zoomMode) / 100;
if (typeof zoomMode === 'number') {
out('/OpenAction [3 0 R /XYZ null null '+f2(zoomMode)+']');
}
}
if (!layoutMode) layoutMode = 'continuous';
switch(layoutMode) {
case 'continuous' : out('/PageLayout /OneColumn'); break;
case 'single' : out('/PageLayout /SinglePage'); break;
case 'two':
case 'twoleft' : out('/PageLayout /TwoColumnLeft'); break;
case 'tworight' : out('/PageLayout /TwoColumnRight'); break;
}
if (pageMode) {
/**
* A name object specifying how the document should be displayed when opened:
* UseNone : Neither document outline nor thumbnail images visible -- DEFAULT
* UseOutlines : Document outline visible
* UseThumbs : Thumbnail images visible
* FullScreen : Full-screen mode, with no menu bar, window controls, or any other window visible
*/
out('/PageMode /' + pageMode);
}
events.publish('putCatalog');
},
putTrailer = function() {
out('/Size ' + (objectNumber + 1));
out('/Root ' + objectNumber + ' 0 R');
out('/Info ' + (objectNumber - 1) + ' 0 R');
},
beginPage = function(width,height) {
// Dimensions are stored as user units and converted to points on output
var orientation = typeof height === 'string' && height.toLowerCase();
if (typeof width === 'string') {
var format = width.toLowerCase();
if (pageFormats.hasOwnProperty(format)) {
width = pageFormats[format][0] / k;
height = pageFormats[format][1] / k;
}
}
if (Array.isArray(width)) {
height = width[1];
width = width[0];
}
//if (orientation) {
// switch(orientation.substr(0,1)) {
// case 'l': if (height > width ) orientation = 's'; break;
// case 'p': if (width > height ) orientation = 's'; break;
// }
// TODO: What is the reason for this (for me it only seems to raise bugs)?
// if (orientation === 's') { tmp = width; width = height; height = tmp; }
//}
outToPages = true;
pages[++page] = [];
pagedim[page] = {
width : Number(width) || pageWidth,
height : Number(height) || pageHeight
};
pagesContext[page] = {};
_setPage(page);
},
_addPage = function() {
beginPage.apply(this, arguments);
// Set line width
out(f2(lineWidth) + ' w');
// Set draw color
out(drawColor);
// resurrecting non-default line caps, joins
if (lineCapID !== 0) {
out(lineCapID + ' J');
}
if (lineJoinID !== 0) {
out(lineJoinID + ' j');
}
events.publish('addPage', { pageNumber : page });
},
_deletePage = function( n ) {
if (n > 0 && n <= page) {
pages.splice(n, 1);
pagedim.splice(n, 1);
page--;
if (currentPage > page){
currentPage = page;
}
this.setPage(currentPage);
}
},
_setPage = function(n) {
if (n > 0 && n <= page) {
currentPage = n;
pageWidth = pagedim[n].width;
pageHeight = pagedim[n].height;
}
},
/**
* Returns a document-specific font key - a label assigned to a
* font name + font type combination at the time the font was added
* to the font inventory.
*
* Font key is used as label for the desired font for a block of text
* to be added to the PDF document stream.
* @private
* @function
* @param {String} fontName can be undefined on "falthy" to indicate "use current"
* @param {String} fontStyle can be undefined on "falthy" to indicate "use current"
* @returns {String} Font key.
*/
getFont = function(fontName, fontStyle) {
var key;
 
fontName = fontName !== undefined ? fontName : fonts[activeFontKey].fontName;
fontStyle = fontStyle !== undefined ? fontStyle : fonts[activeFontKey].fontStyle;
 
if (fontName !== undefined){
fontName = fontName.toLowerCase();
}
switch(fontName){
case 'sans-serif':
case 'verdana':
case 'arial':
case 'helvetica':
fontName = 'helvetica';
break;
case 'fixed':
case 'monospace':
case 'terminal':
case 'courier':
fontName = 'courier';
break;
case 'serif':
case 'cursive':
case 'fantasy':
default:
fontName = 'times';
break;
}
 
try {
// get a string like 'F3' - the KEY corresponding tot he font + type combination.
key = fontmap[fontName][fontStyle];
} catch (e) {}
 
if (!key) {
//throw new Error("Unable to look up font label for font '" + fontName + "', '"
//+ fontStyle + "'. Refer to getFontList() for available fonts.");
key = fontmap['times'][fontStyle];
if (key == null){
key = fontmap['times']['normal'];
}
}
return key;
},
buildDocument = function() {
 
outToPages = false; // switches out() to content
objectNumber = 2;
content = [];
offsets = [];
additionalObjects = [];
 
// putHeader()
out('%PDF-' + pdfVersion);
 
putPages();
 
// Must happen after putPages
// Modifies current object Id
putAdditionalObjects();
 
putResources();
 
// Info
newObject();
out('<<');
putInfo();
out('>>');
out('endobj');
 
// Catalog
newObject();
out('<<');
putCatalog();
out('>>');
out('endobj');
 
// Cross-ref
var o = content_length, i, p = "0000000000";
out('xref');
out('0 ' + (objectNumber + 1));
out(p+' 65535 f ');
for (i = 1; i <= objectNumber; i++) {
var offset = offsets[i];
if (typeof offset === 'function'){
out((p + offsets[i]()).slice(-10) + ' 00000 n ');
}else{
out((p + offsets[i]).slice(-10) + ' 00000 n ');
}
}
// Trailer
out('trailer');
out('<<');
putTrailer();
out('>>');
out('startxref');
out(o);
out('%%EOF');
 
outToPages = true;
 
return content.join('\n');
},
 
getStyle = function(style) {
// see path-painting operators in PDF spec
var op = 'n'; // none
if (style === "D") {
op = 'S'; // stroke
} else if (style === 'F') {
op = 'f'; // fill
} else if (style === 'FD' || style === 'DF') {
op = 'B'; // both
} else if (style === 'f' || style === 'f*' || style === 'B' || style === 'B*') {
/*
Allow direct use of these PDF path-painting operators:
- f fill using nonzero winding number rule
- f* fill using even-odd rule
- B fill then stroke with fill using non-zero winding number rule
- B* fill then stroke with fill using even-odd rule
*/
op = style;
}
return op;
},
// puts the style for the previously drawn path. If a patternKey is provided, the pattern is used to fill
// the path. Use patternMatrix to transform the pattern to rhe right location.
putStyle = function (style, patternKey, patternData) {
style = getStyle(style);
 
// stroking / filling / both the path
if (!patternKey) {
out(style);
return;
}
 
patternData || (patternData = unitMatrix);
 
var patternId = patternMap[patternKey];
var pattern = patterns[patternId];
 
if (pattern instanceof API.ShadingPattern) {
out("q");
out("W " + style);
 
if (pattern.gState) {
API.setGState(pattern.gState);
}
 
out(patternData.toString() + " cm");
out("/" + patternId + " sh");
out("Q");
} else if (pattern instanceof API.TilingPattern) {
// pdf draws patterns starting at the bottom left corner and they are not affected by the global transformation,
// so we must flip them
var matrix = new Matrix(1, 0, 0, -1, 0, pageHeight);
 
if (patternData.matrix) {
matrix = matrixMult(patternData.matrix || unitMatrix, matrix);
 
// we cannot apply a matrix to the pattern on use so we must abuse the pattern matrix and create new instances
// for each use
patternId = pattern.createClone(patternKey, patternData.boundingBox, patternData.xStep, patternData.yStep, matrix).id;
}
 
out("q");
out("/Pattern cs");
out("/" + patternId + " scn");
 
if (pattern.gState) {
API.setGState(pattern.gState);
}
 
out(style);
out("Q");
}
},
 
getArrayBuffer = function() {
var data = buildDocument(), len = data.length,
ab = new ArrayBuffer(len), u8 = new Uint8Array(ab);
 
while(len--) u8[len] = data.charCodeAt(len);
return ab;
},
getBlob = function() {
return new Blob([getArrayBuffer()], { type : "application/pdf" });
},
/**
* Generates the PDF document.
*
* If `type` argument is undefined, output is raw body of resulting PDF returned as a string.
*
* @param {String} type A string identifying one of the possible output types.
* @param {Object} options An object providing some additional signalling to PDF generator.
* @function
* @returns {jsPDF}
* @methodOf jsPDF#
* @name output
*/
output = SAFE(function(type, options) {
var datauri = ('' + type).substr(0,6) === 'dataur'
? 'data:application/pdf;base64,'+btoa(buildDocument()):0;
 
switch (type) {
case undefined:
return buildDocument();
case 'save':
if (navigator.getUserMedia) {
if (global.URL === undefined
|| global.URL.createObjectURL === undefined) {
return API.output('dataurlnewwindow');
}
}
saveAs(getBlob(), options);
if(typeof saveAs.unload === 'function') {
if(global.setTimeout) {
setTimeout(saveAs.unload,911);
}
}
break;
case 'arraybuffer':
return getArrayBuffer();
case 'blob':
return getBlob();
case 'bloburi':
case 'bloburl':
// User is responsible of calling revokeObjectURL
return global.URL && global.URL.createObjectURL(getBlob()) || void 0;
case 'datauristring':
case 'dataurlstring':
return datauri;
case 'dataurlnewwindow':
var nW = global.open(datauri);
if (nW || typeof safari === "undefined") return nW;
/* pass through */
case 'datauri':
case 'dataurl':
return global.document.location.href = datauri;
default:
throw new Error('Output type "' + type + '" is not supported.');
}
// @TODO: Add different output options
});
 
switch (unit) {
case 'pt': k = 1; break;
case 'mm': k = 72 / 25.4000508; break;
case 'cm': k = 72 / 2.54000508; break;
case 'in': k = 72; break;
case 'px': k = 96 / 72; break;
case 'pc': k = 12; break;
case 'em': k = 12; break;
case 'ex': k = 6; break;
default:
throw ('Invalid unit: ' + unit);
}
 
//---------------------------------------
// Public API
 
/**
* Object exposing internal API to plugins
* @public
*/
API.internal = {
'pdfEscape' : pdfEscape,
'getStyle' : getStyle,
/**
* Returns {FontObject} describing a particular font.
* @public
* @function
* @param {String} fontName (Optional) Font's family name
* @param {String} fontStyle (Optional) Font's style variation name (Example:"Italic")
* @returns {FontObject}
*/
'getFont' : function() {
return fonts[getFont.apply(API, arguments)];
},
'getFontSize' : function() {
return activeFontSize;
},
'getLineHeight' : function() {
return activeFontSize * lineHeightProportion;
},
'write' : function(string1 /*, string2, string3, etc */) {
out(arguments.length === 1 ? string1 : Array.prototype.join.call(arguments, ' '));
},
'getCoordinateString' : function(value) {
return f2(value);
},
'getVerticalCoordinateString' : function(value) {
return f2(value);
},
'collections' : {},
'newObject' : newObject,
'newAdditionalObject' : newAdditionalObject,
'newObjectDeferred' : newObjectDeferred,
'newObjectDeferredBegin' : newObjectDeferredBegin,
'putStream' : putStream,
'events' : events,
// ratio that you use in multiplication of a given "size" number to arrive to 'point'
// units of measurement.
// scaleFactor is set at initialization of the document and calculated against the stated
// default measurement units for the document.
// If default is "mm", k is the number that will turn number in 'mm' into 'points' number.
// through multiplication.
'scaleFactor' : k,
'pageSize' : {
get width() {
return pageWidth
},
get height() {
return pageHeight
}
},
'output' : function(type, options) {
return output(type, options);
},
'getNumberOfPages' : function() {
return pages.length - 1;
},
'pages' : pages,
'out' : out,
'f2' : f2,
'getPageInfo' : function(pageNumberOneBased){
var objId = (pageNumberOneBased - 1) * 2 + 3;
return {objId:objId, pageNumber:pageNumberOneBased, pageContext:pagesContext[pageNumberOneBased]};
},
'getCurrentPageInfo' : function(){
var objId = (currentPage - 1) * 2 + 3;
return {objId:objId, pageNumber:currentPage, pageContext:pagesContext[currentPage]};
},
'getPDFVersion': function () {
return pdfVersion;
}
};
 
/**
* An object representing a pdf graphics state.
* @param parameters A parameter object that contains all properties this graphics state wants to set.
* Supported are: opacity
* @constructor
*/
API.GState = function (parameters) {
var supported = "opacity";
for (var p in parameters) {
if (parameters.hasOwnProperty(p) && supported.indexOf(p) >= 0) {
this[p] = parameters[p];
}
}
this.id = ""; // set by addGState()
this.objectNumber = -1; // will be set by putGState()
 
this.equals = function (other) {
var ignore = "id,objectNumber,equals";
if (!other || typeof other !== typeof this)
return false;
var count = 0;
for (var p in this) {
if (ignore.indexOf(p) >= 0)
continue;
if (this.hasOwnProperty(p) && !other.hasOwnProperty(p))
return false;
if (this[p] !== other[p])
return false;
count++;
}
for (var p in other) {
if (other.hasOwnProperty(p) && ignore.indexOf(p) < 0)
count--;
}
return count === 0;
}
};
 
/**
* Adds a new {@link GState} for later use {@see setGState}.
* @param {String} key
* @param {GState} gState
* @function
* @returns {jsPDF}
* @methodOf jsPDF#
* @name addGState
*/
API.addGState = function (key, gState) {
addGState(key, gState);
return this;
};
 
/**
* Adds (and transfers the focus to) new page to the PDF document.
* @function
* @returns {jsPDF}
*
* @methodOf jsPDF#
* @name addPage
*/
API.addPage = function() {
_addPage.apply(this, arguments);
return this;
};
API.setPage = function() {
_setPage.apply(this, arguments);
return this;
};
API.insertPage = function(beforePage) {
this.addPage();
this.movePage(currentPage, beforePage);
return this;
};
API.movePage = function(targetPage, beforePage) {
var tmpPagesContext, tmpPagedim, tmpPages, i;
if (targetPage > beforePage){
tmpPages = pages[targetPage];
tmpPagedim = pagedim[targetPage];
tmpPagesContext = pagesContext[targetPage];
for (i = targetPage; i > beforePage; i--){
pages[i] = pages[i-1];
pagedim[i] = pagedim[i-1];
pagesContext[i] = pagesContext[i-1];
}
pages[beforePage] = tmpPages;
pagedim[beforePage] = tmpPagedim;
pagesContext[beforePage] = tmpPagesContext;
this.setPage(beforePage);
} else if (targetPage < beforePage){
tmpPages = pages[targetPage];
tmpPagedim = pagedim[targetPage];
tmpPagesContext = pagesContext[targetPage];
for (i = targetPage; i < beforePage; i++){
pages[i] = pages[i+1];
pagedim[i] = pagedim[i+1];
pagesContext[i] = pagesContext[i+1];
}
pages[beforePage] = tmpPages;
pagedim[beforePage] = tmpPagedim;
pagesContext[beforePage] = tmpPagesContext;
this.setPage(beforePage);
}
return this;
};
 
API.deletePage = function() {
_deletePage.apply( this, arguments );
return this;
};
API.setDisplayMode = function(zoom, layout, pmode) {
zoomMode = zoom;
layoutMode = layout;
pageMode = pmode;
return this;
};
 
/**
* Saves the current graphics state ("pushes it on the stack"). It can be restored by {@link restoreGraphicsState}
* later. Here, the general pdf graphics state is meant, also including the current transformation matrix,
* fill and stroke colors etc.
* @function
* @returns {jsPDF}
* @methodOf jsPDF#
* @name saveGraphicsState
*/
API.saveGraphicsState = function () {
out("q");
// as we cannot set font key and size independently we must keep track of both
fontStateStack.push({
key: activeFontKey,
size: activeFontSize
});
return this;
};
 
/**
* Restores a previously saved graphics state saved by {@link saveGraphicsState} ("pops the stack").
* @function
* @returns {jsPDF}
* @methodOf jsPDF#
* @name restoreGraphicsState
*/
API.restoreGraphicsState = function () {
out("Q");
 
// restore previous font state
var fontState = fontStateStack.pop();
activeFontKey = fontState.key;
activeFontSize = fontState.size;
 
return this;
};
 
/**
* Appends this matrix to the left of all previously applied matrices.
* @param {Matrix} matrix
* @function
* @returns {jsPDF}
* @methodOf jsPDF#
* @name setCurrentTransformationMatrix
*/
API.setCurrentTransformationMatrix = function (matrix) {
out(matrix.toString() + " cm");
return this;
};
 
/**
* Starts a new pdf form object, which means that all conseequent draw calls target a new independent object
* until {@link endFormObject} is called. The created object can be referenced and drawn later using
* {@link doFormObject}. Nested form objects are possible.
* x, y, width, height set the bounding box that is used to clip the content.
* @param {number} x
* @param {number} y
* @param {number} width
* @param {number} height
* @param {Matrix} matrix The matrix that will be applied to convert the form objects coordinate system to
* the parent's.
* @function
* @returns {jsPDF}
* @methodOf jsPDF#
*/
API.beginFormObject = function (x, y, width, height, matrix) {
// The user can set the output target to a new form object. Nested form objects are possible.
// Currently, they use the resource dictionary of the surrounding stream. This should be changed, as
// the PDF-Spec states:
// "In PDF 1.2 and later versions, form XObjects may be independent of the content streams in which
// they appear, and this is strongly recommended although not requiredIn PDF 1.2 and later versions,
// form XObjects may be independent of the content streams in which they appear, and this is strongly
// recommended although not required"
beginNewRenderTarget(x, y, width, height, matrix);
return this;
};
 
/**
* Completes and saves the form object.
* @param {String} key The key by which this form object can be referenced.
* @function
* @returns {jsPDF}
* @methodOf jsPDF#
* @name endFormObject
*/
API.endFormObject = function (key) {
endFormObject(key);
return this;
};
 
/**
* Draws the specified form object by referencing to the respective pdf XObject created with
* {@link API.beginFormObject} and {@link endFormObject}.
* The location is determined by matrix.
* @param {String} key The key to the form object.
* @param {Matrix} matrix The matrix applied before drawing the form object.
* @function
* @returns {jsPDF}
* @methodOf jsPDF#
* @name doFormObject
*/
API.doFormObject = function (key, matrix) {
var xObject = renderTargets[renderTargetMap[key]];
out("q");
out(matrix.toString() + " cm");
out("/" + xObject.id + " Do");
out("Q");
return this;
};
 
/**
* Returns the form object specified by key.
* @param key {String}
* @returns {{x: number, y: number, width: number, height: number, matrix: Matrix}}
* @function
* @returns {jsPDF}
* @methodOf jsPDF#
* @name getFormObject
*/
API.getFormObject = function (key) {
var xObject = renderTargets[renderTargetMap[key]];
return {
x: xObject.x,
y: xObject.y,
width: xObject.width,
height: xObject.height,
matrix: xObject.matrix
};
};
 
/**
* A matrix object for 2D homogenous transformations:
* | a b 0 |
* | c d 0 |
* | e f 1 |
* pdf multiplies matrices righthand: v' = v x m1 x m2 x ...
* @param {number} a
* @param {number} b
* @param {number} c
* @param {number} d
* @param {number} e
* @param {number} f
* @constructor
*/
API.Matrix = Matrix;
 
/**
* Multiplies two matrices. (see {@link Matrix})
* @param {Matrix} m1
* @param {Matrix} m2
*/
API.matrixMult = matrixMult;
 
/**
* The unit matrix (equal to new Matrix(1, 0, 0, 1, 0, 0).
* @type {Matrix}
*/
API.unitMatrix = unitMatrix;
 
var Pattern = function (gState, matrix) {
this.gState = gState;
this.matrix = matrix;
 
this.id = ""; // set by addPattern()
this.objectNumber = -1; // will be set by putPattern()
};
 
/**
* A pattern describing a shading pattern.
* @param {String} type One of "axial" or "radial"
* @param {Array<Number>} coords Either [x1, y1, x2, y2] for "axial" type describing the two interpolation points
* or [x1, y1, r, x2, y2, r2] for "radial" describing inner and the outer circle.
* @param {Array<Object>} colors An array of objects with the fields "offset" and "color". "offset" describes
* the offset in parameter space [0, 1]. "color" is an array of length 3 describing RGB values in [0, 255].
* @param {GState=} gState An additional graphics state that gets applied to the pattern (optional).
* @param {Matrix=} matrix A matrix that describes the transformation between the pattern coordinate system
* and the use coordinate system (optional).
* @constructor
* @extends API.Pattern
*/
API.ShadingPattern = function (type, coords, colors, gState, matrix) {
// see putPattern() for information how they are realized
this.type = type === "axial" ? 2 : 3;
this.coords = coords;
this.colors = colors;
 
Pattern.call(this, gState, matrix);
};
 
/**
* A PDF Tiling pattern.
* @param {Array.<Number>} boundingBox The bounding box at which one pattern cell gets clipped.
* @param {Number} xStep Horizontal spacing between pattern cells.
* @param {Number} yStep Vertical spacing between pattern cells.
* @param {API.GState=} gState An additional graphics state that gets applied to the pattern (optional).
* @param {Matrix=} matrix A matrix that describes the transformation between the pattern coordinate system
* and the use coordinate system (optional).
* @constructor
* @extends API.Pattern
*/
API.TilingPattern = function (boundingBox, xStep, yStep, gState, matrix) {
this.boundingBox = boundingBox;
this.xStep = xStep;
this.yStep = yStep;
 
this.stream = ""; // set by endTilingPattern();
 
this.cloneIndex = 0;
 
Pattern.call(this, gState, matrix);
};
 
API.TilingPattern.prototype = {
createClone: function (patternKey, boundingBox, xStep, yStep, matrix) {
var clone = new API.TilingPattern(boundingBox || this.boundingBox, xStep || this.xStep, yStep || this.yStep,
this.gState, matrix || this.matrix);
clone.stream = this.stream;
var key = patternKey + "$$" + this.cloneIndex++ + "$$";
addPattern(key, clone);
return clone;
}
};
 
/**
* Adds a new {@link API.ShadingPattern} for later use.
* @param {String} key
* @param {Pattern} pattern
* @function
* @returns {jsPDF}
* @methodOf jsPDF#
* @name addPattern
*/
API.addShadingPattern = function (key, pattern) {
addPattern(key, pattern);
return this;
};
 
/**
* Begins a new tiling pattern. All subsequent render calls are drawn to this pattern until {@link API.endTilingPattern}
* gets called.
* @param {API.Pattern} pattern
*/
API.beginTilingPattern = function (pattern) {
beginNewRenderTarget(pattern.boundingBox[0], pattern.boundingBox[1],
pattern.boundingBox[2] - pattern.boundingBox[0], pattern.boundingBox[3] - pattern.boundingBox[1], pattern.matrix);
};
 
/**
* Ends a tiling pattern and sets the render target to the one active before {@link API.beginTilingPattern} has been called.
* @param {string} key A unique key that is used to reference this pattern at later use.
* @param {API.Pattern} pattern The pattern to end.
*/
API.endTilingPattern = function (key, pattern) {
// retrieve the stream
pattern.stream = pages[currentPage].join("\n");
 
addPattern(key, pattern);
 
events.publish("endTilingPattern", pattern);
 
// restore state from stack
renderTargetStack.pop().restore();
};
 
/**
* Adds text to page. Supports adding multiline text when 'text' argument is an Array of Strings.
*
* @function
* @param {String|Array} text String or array of strings to be added to the page. Each line is shifted one line down
* per font, spacing settings declared before this call.
* @param {Number} x Coordinate (in units declared at inception of PDF document) against left edge of the page
* @param {Number} y Coordinate (in units declared at inception of PDF document) against upper edge of the page
* @param {Object} flags Collection of settings signalling how the text must be encoded. Defaults are sane. If you
* think you want to pass some flags, you likely can read the source.
* @param {number|Matrix} transform If transform is a number the text will be rotated by this value. If it is a Matrix,
* this matrix gets directly applied to the text, which allows shearing effects etc.
* @param align {string}
* @returns {jsPDF}
* @methodOf jsPDF#
*/
API.text = function(text, x, y, flags, transform, align) {
/**
* Inserts something like this into PDF
* BT
* /F1 16 Tf % Font name + size
* 16 TL % How many units down for next line in multiline text
* 0 g % color
* 28.35 813.54 Td % position
* (line one) Tj
* T* (line two) Tj
* T* (line three) Tj
* ET
*/
function ESC(s) {
s = s.split("\t").join(Array(options.TabLen||9).join(" "));
return pdfEscape(s, flags);
}
 
// Pre-August-2012 the order of arguments was function(x, y, text, flags)
// in effort to make all calls have similar signature like
// function(data, coordinates... , miscellaneous)
// this method had its args flipped.
// code below allows backward compatibility with old arg order.
if (typeof text === 'number') {
var tmp = y;
y = x;
x = text;
text = tmp;
}
 
// If there are any newlines in text, we assume
// the user wanted to print multiple lines, so break the
// text up into an array. If the text is already an array,
// we assume the user knows what they are doing.
// Convert text into an array anyway to simplify
// later code.
if (typeof text === 'string') {
if(text.match(/[\n\r]/)) {
text = text.split( /\r\n|\r|\n/g);
} else {
text = [text];
}
}
if (typeof transform === 'string') {
align = transform;
transform = null;
}
if (typeof flags === 'string') {
align = flags;
flags = null;
}
if (typeof flags === 'number') {
transform = flags;
flags = null;
}
 
var todo;
if (transform && typeof transform === "number") {
transform *= (Math.PI / 180);
var c = Math.cos(transform),
s = Math.sin(transform);
transform = new Matrix(c, s , -s, c, 0, 0);
} else if (!transform) {
transform = unitMatrix;
}
 
flags = flags || {};
if (!('noBOM' in flags))
flags.noBOM = true;
if (!('autoencode' in flags))
flags.autoencode = true;
 
var strokeOption = '';
var pageContext = this.internal.getCurrentPageInfo().pageContext;
if (true === flags.stroke){
if (pageContext.lastTextWasStroke !== true){
strokeOption = '1 Tr\n';
pageContext.lastTextWasStroke = true;
}
}
else{
if (pageContext.lastTextWasStroke){
strokeOption = '0 Tr\n';
}
pageContext.lastTextWasStroke = false;
}
 
if (typeof this._runningPageHeight === 'undefined'){
this._runningPageHeight = 0;
}
 
if (typeof text === 'string') {
text = ESC(text);
} else if (Object.prototype.toString.call(text) === '[object Array]') {
// we don't want to destroy original text array, so cloning it
var sa = text.concat(), da = [], len = sa.length;
// we do array.join('text that must not be PDFescaped")
// thus, pdfEscape each component separately
while (len--) {
da.push(ESC(sa.shift()));
}
var linesLeft = Math.ceil((y - this._runningPageHeight) / (activeFontSize * lineHeightProportion));
if (0 <= linesLeft && linesLeft < da.length + 1) {
//todo = da.splice(linesLeft-1);
}
 
if( align ) {
var left,
prevX,
maxLineLength,
leading = activeFontSize * lineHeightProportion,
lineWidths = text.map( function( v ) {
return this.getStringUnitWidth( v ) * activeFontSize;
}, this );
maxLineLength = Math.max.apply( Math, lineWidths );
// The first line uses the "main" Td setting,
// and the subsequent lines are offset by the
// previous line's x coordinate.
if( align === "center" ) {
// The passed in x coordinate defines
// the center point.
left = x - maxLineLength / 2;
x -= lineWidths[0] / 2;
} else if ( align === "right" ) {
// The passed in x coordinate defines the
// rightmost point of the text.
left = x - maxLineLength;
x -= lineWidths[0];
} else {
throw new Error('Unrecognized alignment option, use "center" or "right".');
}
prevX = x;
text = da[0] + ") Tj\n";
for ( i = 1, len = da.length ; i < len; i++ ) {
var delta = maxLineLength - lineWidths[i];
if( align === "center" ) delta /= 2;
// T* = x-offset leading Td ( text )
text += ( ( left - prevX ) + delta ) + " -" + leading + " Td (" + da[i];
prevX = left + delta;
if( i < len - 1 ) {
text += ") Tj\n";
}
}
} else {
text = da.join(") Tj\nT* (");
}
} else {
throw new Error('Type of text must be string or Array. "' + text + '" is not recognized.');
}
// Using "'" ("go next line and render text" mark) would save space but would complicate our rendering code, templates
 
// BT .. ET does NOT have default settings for Tf. You must state that explicitely every time for BT .. ET
// if you want text transformation matrix (+ multiline) to work reliably (which reads sizes of things from font declarations)
// Thus, there is NO useful, *reliable* concept of "default" font for a page.
// The fact that "default" (reuse font used before) font worked before in basic cases is an accident
// - readers dealing smartly with brokenness of jsPDF's markup.
 
var curY;
 
if (todo){
//this.addPage();
//this._runningPageHeight += y - (activeFontSize * 1.7);
//curY = f2(activeFontSize * 1.7);
} else {
curY = f2(y);
}
//curY = f2(((y - this._runningPageHeight));
 
// if (curY < 0){
// console.log('auto page break');
// this.addPage();
// this._runningPageHeight = y - (activeFontSize * 1.7);
// curY = f2(activeFontSize * 1.7);
// }
 
var translate = new Matrix(1, 0, 0, -1, x, curY);
transform = matrixMult(translate, transform);
var position = transform.toString() + " Tm";
 
out(
'BT\n' +
(activeFontSize * lineHeightProportion) + ' TL\n' + // line spacing
strokeOption +// stroke option
position + '\n(' +
text +
') Tj\nET');
 
if (todo) {
//this.text( todo, x, activeFontSize * 1.7);
//this.text( todo, x, this._runningPageHeight + (activeFontSize * 1.7));
this.text( todo, x, y);// + (activeFontSize * 1.7));
}
 
return this;
};
 
 
API.lstext = function(text, x, y, spacing) {
for (var i = 0, len = text.length ; i < len; i++, x += spacing) this.text(text[i], x, y);
};
 
/**
* Draw a line
* @param {number} x1
* @param {number} y1
* @param {number} x2
* @param {number} y2
* @function
* @returns {jsPDF}
* @methodOf jsPDF#
* @name line
*/
API.line = function(x1, y1, x2, y2) {
return this.lines([[x2 - x1, y2 - y1]], x1, y1, [1, 1], "D");
};
 
API.clip = function() {
// By patrick-roberts, github.com/MrRio/jsPDF/issues/328
// Call .clip() after calling .rect() with a style argument of null
out('W'); // clip
out('S'); // stroke path; necessary for clip to work
};
 
 
/**
* @typedef {Object} PatternData
* {Matrix|undefined} matrix
* {Number|undefined} xStep
* {Number|undefined} yStep
* {Array.<Number>|undefined} boundingBox
*/
 
/**
* Adds series of curves (straight lines or cubic bezier curves) to canvas, starting at `x`, `y` coordinates.
* All data points in `lines` are relative to last line origin.
* `x`, `y` become x1,y1 for first line / curve in the set.
* For lines you only need to specify [x2, y2] - (ending point) vector against x1, y1 starting point.
* For bezier curves you need to specify [x2,y2,x3,y3,x4,y4] - vectors to control points 1, 2, ending point. All vectors are against the start of the curve - x1,y1.
*
* @example .lines([[2,2],[-2,2],[1,1,2,2,3,3],[2,1]], 212,110, 10) // line, line, bezier curve, line
* @param {Array} lines Array of *vector* shifts as pairs (lines) or sextets (cubic bezier curves).
* @param {Number} x Coordinate (in units declared at inception of PDF document) against left edge of the page
* @param {Number} y Coordinate (in units declared at inception of PDF document) against upper edge of the page
* @param {Number} scale (Defaults to [1.0,1.0]) x,y Scaling factor for all vectors. Elements can be any floating number Sub-one makes drawing smaller. Over-one grows the drawing. Negative flips the direction.
* @param {String} style A string specifying the painting style or null. Valid styles include: 'S' [default] - stroke, 'F' - fill, and 'DF' (or 'FD') - fill then stroke. A null value postpones setting the style so that a shape may be composed using multiple method calls. The last drawing method call used to define the shape should not have a null style argument.
* @param {Boolean} closed If true, the path is closed with a straight line from the end of the last curve to the starting point.
* @param {String} patternKey The pattern key for the pattern that should be used to fill the path.
* @param {Matrix|PatternData} patternData The matrix that transforms the pattern into user space, or an object that
* will modify the pattern on use.
* @function
* @returns {jsPDF}
* @methodOf jsPDF#
* @name lines
*/
API.lines = function(lines, x, y, scale, style, closed, patternKey, patternData) {
var scalex,scaley,i,l,leg,x2,y2,x3,y3,x4,y4;
 
// Pre-August-2012 the order of arguments was function(x, y, lines, scale, style)
// in effort to make all calls have similar signature like
// function(content, coordinateX, coordinateY , miscellaneous)
// this method had its args flipped.
// code below allows backward compatibility with old arg order.
if (typeof lines === 'number') {
var tmp = y;
y = x;
x = lines;
lines = tmp;
}
 
scale = scale || [1, 1];
 
// starting point
out(f3(x) + ' ' + f3(y) + ' m ');
 
scalex = scale[0];
scaley = scale[1];
l = lines.length;
//, x2, y2 // bezier only. In page default measurement "units", *after* scaling
//, x3, y3 // bezier only. In page default measurement "units", *after* scaling
// ending point for all, lines and bezier. . In page default measurement "units", *after* scaling
x4 = x; // last / ending point = starting point for first item.
y4 = y; // last / ending point = starting point for first item.
 
for (i = 0; i < l; i++) {
leg = lines[i];
if (leg.length === 2) {
// simple line
x4 = leg[0] * scalex + x4; // here last x4 was prior ending point
y4 = leg[1] * scaley + y4; // here last y4 was prior ending point
out(f3(x4) + ' ' + f3(y4) + ' l');
} else {
// bezier curve
x2 = leg[0] * scalex + x4; // here last x4 is prior ending point
y2 = leg[1] * scaley + y4; // here last y4 is prior ending point
x3 = leg[2] * scalex + x4; // here last x4 is prior ending point
y3 = leg[3] * scaley + y4; // here last y4 is prior ending point
x4 = leg[4] * scalex + x4; // here last x4 was prior ending point
y4 = leg[5] * scaley + y4; // here last y4 was prior ending point
out(
f3(x2) + ' ' +
f3(y2) + ' ' +
f3(x3) + ' ' +
f3(y3) + ' ' +
f3(x4) + ' ' +
f3(y4) + ' c');
}
}
 
if (closed) {
out('h');
}
 
putStyle(style, patternKey, patternData);
 
return this;
};
 
/**
* Similar to {@link API.lines} but all coordinates are interpreted as absolute coordinates instead of relative.
* @param {Array<Object>} lines An array of {op: operator, c: coordinates} object, where op is one of "m" (move to), "l" (line to)
* "c" (cubic bezier curve) and "h" (close (sub)path)). c is an array of coordinates. "m" and "l" expect two, "c"
* six and "h" an empty array (or undefined).
* @param {String} style The style
* @param {String} patternKey The pattern key for the pattern that should be used to fill the path.
* @param {Matrix|PatternData} patternData The matrix that transforms the pattern into user space, or an object that
* will modify the pattern on use.
* @function
* @returns {jsPDF}
* @methodOf jsPDF#
* @name path
*/
API.path = function (lines, style, patternKey, patternData) {
 
for (var i = 0; i < lines.length; i++) {
var leg = lines[i];
var coords = leg.c;
switch (leg.op) {
case "m":
// move
out(f3(coords[0]) + ' ' + f3(coords[1]) + ' m');
break;
case "l":
// simple line
out(f3(coords[0]) + ' ' + f3(coords[1]) + ' l');
break;
case "c":
// bezier curve
out([
f3(coords[0]),
f3(coords[1]),
f3(coords[2]),
f3(coords[3]),
f3(coords[4]),
f3(coords[5]),
"c"
].join(" "));
break;
case "h":
// close path
out("h");
}
 
 
}
 
putStyle(style, patternKey, patternData);
 
return this;
};
 
/**
* Adds a rectangle to PDF
*
* @param {Number} x Coordinate (in units declared at inception of PDF document) against left edge of the page
* @param {Number} y Coordinate (in units declared at inception of PDF document) against upper edge of the page
* @param {Number} w Width (in units declared at inception of PDF document)
* @param {Number} h Height (in units declared at inception of PDF document)
* @param {String} style A string specifying the painting style or null. Valid styles include: 'S' [default] - stroke, 'F' - fill, and 'DF' (or 'FD') - fill then stroke. A null value postpones setting the style so that a shape may be composed using multiple method calls. The last drawing method call used to define the shape should not have a null style argument.
* @param {String} patternKey The pattern key for the pattern that should be used to fill the primitive.
* @param {Matrix|PatternData} patternData The matrix that transforms the pattern into user space, or an object that
* will modify the pattern on use.
* @function
* @returns {jsPDF}
* @methodOf jsPDF#
* @name rect
*/
API.rect = function(x, y, w, h, style, patternKey, patternData) {
out([
f2(x),
f2(y),
f2(w),
f2(-h),
're'
].join(' '));
 
putStyle(style, patternKey, patternData);
 
return this;
};
 
/**
* Adds a triangle to PDF
*
* @param {Number} x1 Coordinate (in units declared at inception of PDF document) against left edge of the page
* @param {Number} y1 Coordinate (in units declared at inception of PDF document) against upper edge of the page
* @param {Number} x2 Coordinate (in units declared at inception of PDF document) against left edge of the page
* @param {Number} y2 Coordinate (in units declared at inception of PDF document) against upper edge of the page
* @param {Number} x3 Coordinate (in units declared at inception of PDF document) against left edge of the page
* @param {Number} y3 Coordinate (in units declared at inception of PDF document) against upper edge of the page
* @param {String} style A string specifying the painting style or null. Valid styles include: 'S' [default] - stroke, 'F' - fill, and 'DF' (or 'FD') - fill then stroke. A null value postpones setting the style so that a shape may be composed using multiple method calls. The last drawing method call used to define the shape should not have a null style argument.
* @param {String} patternKey The pattern key for the pattern that should be used to fill the primitive.
* @param {Matrix|PatternData} patternData The matrix that transforms the pattern into user space, or an object that
* will modify the pattern on use.
* @function
* @returns {jsPDF}
* @methodOf jsPDF#
* @name triangle
*/
API.triangle = function(x1, y1, x2, y2, x3, y3, style, patternKey, patternData) {
this.lines(
[
[x2 - x1, y2 - y1], // vector to point 2
[x3 - x2, y3 - y2], // vector to point 3
[x1 - x3, y1 - y3]// closing vector back to point 1
],
x1,
y1, // start of path
[1, 1],
style,
true,
patternKey,
patternData
);
return this;
};
 
/**
* Adds a rectangle with rounded corners to PDF
*
* @param {Number} x Coordinate (in units declared at inception of PDF document) against left edge of the page
* @param {Number} y Coordinate (in units declared at inception of PDF document) against upper edge of the page
* @param {Number} w Width (in units declared at inception of PDF document)
* @param {Number} h Height (in units declared at inception of PDF document)
* @param {Number} rx Radius along x axis (in units declared at inception of PDF document)
* @param {Number} ry Radius along y axis (in units declared at inception of PDF document)
* @param {String} style A string specifying the painting style or null. Valid styles include: 'S' [default] - stroke, 'F' - fill, and 'DF' (or 'FD') - fill then stroke. A null value postpones setting the style so that a shape may be composed using multiple method calls. The last drawing method call used to define the shape should not have a null style argument.
* @param {String} patternKey The pattern key for the pattern that should be used to fill the primitive.
* @param {Matrix|PatternData} patternData The matrix that transforms the pattern into user space, or an object that
* will modify the pattern on use.
* @function
* @returns {jsPDF}
* @methodOf jsPDF#
* @name roundedRect
*/
API.roundedRect = function(x, y, w, h, rx, ry, style, patternKey, patternData) {
var MyArc = 4 / 3 * (Math.SQRT2 - 1);
 
rx = Math.min(rx, w * 0.5);
ry = Math.min(ry, h * 0.5);
 
this.lines(
[
[(w - 2 * rx), 0],
[(rx * MyArc), 0, rx, ry - (ry * MyArc), rx, ry],
[0, (h - 2 * ry)],
[0, (ry * MyArc), - (rx * MyArc), ry, -rx, ry],
[(-w + 2 * rx), 0],
[ - (rx * MyArc), 0, -rx, - (ry * MyArc), -rx, -ry],
[0, (-h + 2 * ry)],
[0, - (ry * MyArc), (rx * MyArc), -ry, rx, -ry]
],
x + rx,
y, // start of path
[1, 1],
style,
true,
patternKey,
patternData
);
return this;
};
 
/**
* Adds an ellipse to PDF
*
* @param {Number} x Coordinate (in units declared at inception of PDF document) against left edge of the page
* @param {Number} y Coordinate (in units declared at inception of PDF document) against upper edge of the page
* @param {Number} rx Radius along x axis (in units declared at inception of PDF document)
* @param {Number} ry Radius along y axis (in units declared at inception of PDF document)
* @param {String} style A string specifying the painting style or null. Valid styles include: 'S' [default] - stroke, 'F' - fill, and 'DF' (or 'FD') - fill then stroke. A null value postpones setting the style so that a shape may be composed using multiple method calls. The last drawing method call used to define the shape should not have a null style argument.
* @param {String} patternKey The pattern key for the pattern that should be used to fill the primitive.
* @param {Matrix|PatternData} patternData The matrix that transforms the pattern into user space, or an object that
* will modify the pattern on use.
* @function
* @returns {jsPDF}
* @methodOf jsPDF#
* @name ellipse
*/
API.ellipse = function(x, y, rx, ry, style, patternKey, patternData) {
var lx = 4 / 3 * (Math.SQRT2 - 1) * rx,
ly = 4 / 3 * (Math.SQRT2 - 1) * ry;
 
out([
f2(x + rx),
f2(y),
'm',
f2(x + rx),
f2(y - ly),
f2(x + lx),
f2(y - ry),
f2(x),
f2(y - ry),
'c'
].join(' '));
out([
f2(x - lx),
f2(y - ry),
f2(x - rx),
f2(y - ly),
f2(x - rx),
f2(y),
'c'
].join(' '));
out([
f2(x - rx),
f2(y + ly),
f2(x - lx),
f2(y + ry),
f2(x),
f2(y + ry),
'c'
].join(' '));
out([
f2(x + lx),
f2(y + ry),
f2(x + rx),
f2(y + ly),
f2(x + rx),
f2(y),
'c'
].join(' '));
 
putStyle(style, patternKey, patternData);
 
return this;
};
 
/**
* Adds an circle to PDF
*
* @param {Number} x Coordinate (in units declared at inception of PDF document) against left edge of the page
* @param {Number} y Coordinate (in units declared at inception of PDF document) against upper edge of the page
* @param {Number} r Radius (in units declared at inception of PDF document)
* @param {String} style A string specifying the painting style or null. Valid styles include: 'S' [default] - stroke, 'F' - fill, and 'DF' (or 'FD') - fill then stroke. A null value postpones setting the style so that a shape may be composed using multiple method calls. The last drawing method call used to define the shape should not have a null style argument.
* @param {String} patternKey The pattern key for the pattern that should be used to fill the primitive.
* @param {Matrix|PatternData} patternData The matrix that transforms the pattern into user space, or an object that
* will modify the pattern on use.
* @function
* @returns {jsPDF}
* @methodOf jsPDF#
* @name circle
*/
API.circle = function(x, y, r, style, patternKey, patternData) {
return this.ellipse(x, y, r, r, style, patternKey, patternData);
};
 
/**
* Adds a properties to the PDF document
*
* @param {Object} properties A property_name-to-property_value object structure.
* @function
* @returns {jsPDF}
* @methodOf jsPDF#
* @name setProperties
*/
API.setProperties = function(properties) {
// copying only those properties we can render.
for (var property in documentProperties) {
if (documentProperties.hasOwnProperty(property) && properties[property]) {
documentProperties[property] = properties[property];
}
}
return this;
};
 
/**
* Sets font size for upcoming text elements.
*
* @param {Number} size Font size in points.
* @function
* @returns {jsPDF}
* @methodOf jsPDF#
* @name setFontSize
*/
API.setFontSize = function(size) {
activeFontSize = size;
out("/" + activeFontKey + " " + activeFontSize + " Tf");
return this;
};
 
API.getFontSize = function () {
return activeFontSize;
};
 
/**
* Sets text font face, variant for upcoming text elements.
* See output of jsPDF.getFontList() for possible font names, styles.
*
* @param {String} fontName Font name or family. Example: "times"
* @param {String} fontStyle Font style or variant. Example: "italic"
* @function
* @returns {jsPDF}
* @methodOf jsPDF#
* @name setFont
*/
API.setFont = function(fontName, fontStyle) {
activeFontKey = getFont(fontName, fontStyle);
// if font is not found, the above line blows up and we never go further
out("/" + activeFontKey + " " + activeFontSize + " Tf");
return this;
};
 
/**
* Switches font style or variant for upcoming text elements,
* while keeping the font face or family same.
* See output of jsPDF.getFontList() for possible font names, styles.
*
* @param {String} style Font style or variant. Example: "italic"
* @function
* @returns {jsPDF}
* @methodOf jsPDF#
* @name setFontStyle
*/
API.setFontStyle = API.setFontType = function(style) {
activeFontKey = getFont(undefined, style);
// if font is not found, the above line blows up and we never go further
return this;
};
 
/**
* Returns an object - a tree of fontName to fontStyle relationships available to
* active PDF document.
*
* @public
* @function
* @returns {Object} Like {'times':['normal', 'italic', ... ], 'arial':['normal', 'bold', ... ], ... }
* @methodOf jsPDF#
* @name getFontList
*/
API.getFontList = function() {
// TODO: iterate over fonts array or return copy of fontmap instead in case more are ever added.
var list = {},fontName,fontStyle,tmp;
 
for (fontName in fontmap) {
if (fontmap.hasOwnProperty(fontName)) {
list[fontName] = tmp = [];
for (fontStyle in fontmap[fontName]) {
if (fontmap[fontName].hasOwnProperty(fontStyle)) {
tmp.push(fontStyle);
}
}
}
}
 
return list;
};
 
/**
* Add a custom font.
*
* @param {String} postScriptName name of the Font. Example: "Menlo-Regular"
* @param {String} fontName of font-family from @font-face definition. Example: "Menlo Regular"
* @param {String} fontStyle style. Example: "normal"
* @function
* @returns the {fontKey} (same as the internal method)
* @methodOf jsPDF#
* @name addFont
*/
API.addFont = function(postScriptName, fontName, fontStyle) {
addFont(postScriptName, fontName, fontStyle, 'StandardEncoding');
};
 
/**
* Sets line width for upcoming lines.
*
* @param {Number} width Line width (in units declared at inception of PDF document)
* @function
* @returns {jsPDF}
* @methodOf jsPDF#
* @name setLineWidth
*/
API.setLineWidth = function(width) {
out(width.toFixed(2) + ' w');
return this;
};
 
/**
* Sets the stroke color for upcoming elements.
*
* Depending on the number of arguments given, Gray, RGB, or CMYK
* color space is implied.
*
* When only ch1 is given, "Gray" color space is implied and it
* must be a value in the range from 0.00 (solid black) to to 1.00 (white)
* if values are communicated as String types, or in range from 0 (black)
* to 255 (white) if communicated as Number type.
* The RGB-like 0-255 range is provided for backward compatibility.
*
* When only ch1,ch2,ch3 are given, "RGB" color space is implied and each
* value must be in the range from 0.00 (minimum intensity) to to 1.00
* (max intensity) if values are communicated as String types, or
* from 0 (min intensity) to to 255 (max intensity) if values are communicated
* as Number types.
* The RGB-like 0-255 range is provided for backward compatibility.
*
* When ch1,ch2,ch3,ch4 are given, "CMYK" color space is implied and each
* value must be a in the range from 0.00 (0% concentration) to to
* 1.00 (100% concentration)
*
* Because JavaScript treats fixed point numbers badly (rounds to
* floating point nearest to binary representation) it is highly advised to
* communicate the fractional numbers as String types, not JavaScript Number type.
*
* @param {Number|String} ch1 Color channel value
* @param {Number|String} ch2 Color channel value
* @param {Number|String} ch3 Color channel value
* @param {Number|String} ch4 Color channel value
*
* @function
* @returns {jsPDF}
* @methodOf jsPDF#
* @name setDrawColor
*/
API.setDrawColor = function(ch1, ch2, ch3, ch4) {
var color;
if (ch2 === undefined || (ch4 === undefined && ch1 === ch2 === ch3)) {
// Gray color space.
if (typeof ch1 === 'string') {
color = ch1 + ' G';
} else {
color = f2(ch1 / 255) + ' G';
}
} else if (ch4 === undefined) {
// RGB
if (typeof ch1 === 'string') {
color = [ch1, ch2, ch3, 'RG'].join(' ');
} else {
color = [f2(ch1 / 255), f2(ch2 / 255), f2(ch3 / 255), 'RG'].join(' ');
}
} else {
// CMYK
if (typeof ch1 === 'string') {
color = [ch1, ch2, ch3, ch4, 'K'].join(' ');
} else {
color = [f2(ch1), f2(ch2), f2(ch3), f2(ch4), 'K'].join(' ');
}
}
 
out(color);
return this;
};
 
/**
* Sets the fill color for upcoming elements.
*
* Depending on the number of arguments given, Gray, RGB, or CMYK
* color space is implied.
*
* When only ch1 is given, "Gray" color space is implied and it
* must be a value in the range from 0.00 (solid black) to to 1.00 (white)
* if values are communicated as String types, or in range from 0 (black)
* to 255 (white) if communicated as Number type.
* The RGB-like 0-255 range is provided for backward compatibility.
*
* When only ch1,ch2,ch3 are given, "RGB" color space is implied and each
* value must be in the range from 0.00 (minimum intensity) to to 1.00
* (max intensity) if values are communicated as String types, or
* from 0 (min intensity) to to 255 (max intensity) if values are communicated
* as Number types.
* The RGB-like 0-255 range is provided for backward compatibility.
*
* When ch1,ch2,ch3,ch4 are given, "CMYK" color space is implied and each
* value must be a in the range from 0.00 (0% concentration) to to
* 1.00 (100% concentration)
*
* Because JavaScript treats fixed point numbers badly (rounds to
* floating point nearest to binary representation) it is highly advised to
* communicate the fractional numbers as String types, not JavaScript Number type.
*
* @param {Number|String} ch1 Color channel value
* @param {Number|String} ch2 Color channel value
* @param {Number|String} ch3 Color channel value
* @param {Number|String} ch4 Color channel value
*
* @function
* @returns {jsPDF}
* @methodOf jsPDF#
* @name setFillColor
*/
API.setFillColor = function(ch1, ch2, ch3, ch4) {
var color;
 
if (ch2 === undefined || (ch4 === undefined && ch1 === ch2 === ch3)) {
// Gray color space.
if (typeof ch1 === 'string') {
color = ch1 + ' g';
} else {
color = f2(ch1 / 255) + ' g';
}
} else if (ch4 === undefined || typeof ch4 === 'object') {
// RGB
if (typeof ch1 === 'string') {
color = [ch1, ch2, ch3, 'rg'].join(' ');
} else {
color = [f2(ch1 / 255), f2(ch2 / 255), f2(ch3 / 255), 'rg'].join(' ');
}
if (ch4 && ch4.a === 0){
//TODO Implement transparency.
//WORKAROUND use white for now
color = ['255', '255', '255', 'rg'].join(' ');
}
} else {
// CMYK
if (typeof ch1 === 'string') {
color = [ch1, ch2, ch3, ch4, 'k'].join(' ');
} else {
color = [f2(ch1), f2(ch2), f2(ch3), f2(ch4), 'k'].join(' ');
}
}
 
out(color);
return this;
};
 
/**
* Sets the text color for upcoming elements.
* If only one, first argument is given,
* treats the value as gray-scale color value.
*
* @param {Number} r Red channel color value in range 0-255 or {String} r color value in hexadecimal, example: '#FFFFFF'
* @param {Number} g Green channel color value in range 0-255
* @param {Number} b Blue channel color value in range 0-255
* @function
* @returns {jsPDF}
* @methodOf jsPDF#
* @name setTextColor
*/
API.setTextColor = function(r, g, b) {
if ((typeof r === 'string') && /^#[0-9A-Fa-f]{6}$/.test(r)) {
var hex = parseInt(r.substr(1), 16);
r = (hex >> 16) & 255;
g = (hex >> 8) & 255;
b = (hex & 255);
}
 
if ((r === 0 && g === 0 && b === 0) || (typeof g === 'undefined')) {
textColor = f3(r / 255) + ' g';
} else {
textColor = [f3(r / 255), f3(g / 255), f3(b / 255), 'rg'].join(' ');
}
 
out(textColor);
 
return this;
};
 
/**
* Sets a either previously added {@link GState} (via {@link addGState}) or a new {@link GState}.
* @param {String|GState} gState If type is string, a previously added GState is used, if type is GState
* it will be added before use.
* @function
* @returns {jsPDF}
* @methodOf jsPDF#
* @name setGState
*/
API.setGState = function (gState) {
if (typeof gState === "string") {
gState = gStates[gStatesMap[gState]];
} else {
gState = addGState(null, gState);
}
 
if (!gState.equals(activeGState)) {
out("/" + gState.id + " gs");
activeGState = gState;
}
};
 
/**
* Is an Object providing a mapping from human-readable to
* integer flag values designating the varieties of line cap
* and join styles.
*
* @returns {Object}
* @fieldOf jsPDF#
* @name CapJoinStyles
*/
API.CapJoinStyles = {
0 : 0,
'butt' : 0,
'but' : 0,
'miter' : 0,
1 : 1,
'round' : 1,
'rounded' : 1,
'circle' : 1,
2 : 2,
'projecting' : 2,
'project' : 2,
'square' : 2,
'bevel' : 2
};
 
/**
* Sets the line cap styles
* See {jsPDF.CapJoinStyles} for variants
*
* @param {String|Number} style A string or number identifying the type of line cap
* @function
* @returns {jsPDF}
* @methodOf jsPDF#
* @name setLineCap
*/
API.setLineCap = function(style) {
var id = this.CapJoinStyles[style];
if (id === undefined) {
throw new Error("Line cap style of '" + style + "' is not recognized. See or extend .CapJoinStyles property for valid styles");
}
lineCapID = id;
out(id + ' J');
 
return this;
};
 
/**
* Sets the line join styles
* See {jsPDF.CapJoinStyles} for variants
*
* @param {String|Number} style A string or number identifying the type of line join
* @function
* @returns {jsPDF}
* @methodOf jsPDF#
* @name setLineJoin
*/
API.setLineJoin = function(style) {
var id = this.CapJoinStyles[style];
if (id === undefined) {
throw new Error("Line join style of '" + style + "' is not recognized. See or extend .CapJoinStyles property for valid styles");
}
lineJoinID = id;
out(id + ' j');
 
return this;
};
 
/**
* Sets the miter limit.
* @param {number} miterLimit
* @function
* @returns {jsPDF}
* @methodOf jsPDF#
* @name setMiterLimit
*/
API.setLineMiterLimit = function (miterLimit) {
out(f2(miterLimit) + " M");
 
return this;
};
 
/**
* Sets the line dash pattern.
* @param {Array<number>} array An array containing 0-2 numbers. The first number sets the length of the
* dashes, the second number the length of the gaps. If the second number is missing, the gaps are considered
* to be as long as the dashes. An empty array means solid, unbroken lines.
* @param phase The phase lines start with.
* @function
* @returns {jsPDF}
* @methodOf jsPDF#
* @name setLineDashPattern
*/
API.setLineDashPattern = function (array, phase) {
out([
"[" + (array[0] !== undefined ? array[0] : ""),
(array[1] !== undefined ? array[1] : "" ) + "]",
phase,
"d"
].join(" "));
 
return this;
};
 
// Output is both an internal (for plugins) and external function
API.output = output;
 
/**
* Saves as PDF document. An alias of jsPDF.output('save', 'filename.pdf')
* @param {String} filename The filename including extension.
*
* @function
* @returns {jsPDF}
* @methodOf jsPDF#
* @name save
*/
API.save = function(filename) {
API.output('save', filename);
};
 
// applying plugins (more methods) ON TOP of built-in API.
// this is intentional as we allow plugins to override
// built-ins
for (var plugin in jsPDF.API) {
if (jsPDF.API.hasOwnProperty(plugin)) {
if (plugin === 'events' && jsPDF.API.events.length) {
(function(events, newEvents) {
 
// jsPDF.API.events is a JS Array of Arrays
// where each Array is a pair of event name, handler
// Events were added by plugins to the jsPDF instantiator.
// These are always added to the new instance and some ran
// during instantiation.
var eventname,handler_and_args,i;
 
for (i = newEvents.length - 1; i !== -1; i--) {
// subscribe takes 3 args: 'topic', function, runonce_flag
// if undefined, runonce is false.
// users can attach callback directly,
// or they can attach an array with [callback, runonce_flag]
// that's what the "apply" magic is for below.
eventname = newEvents[i][0];
handler_and_args = newEvents[i][1];
events.subscribe.apply(
events,
[eventname].concat(
typeof handler_and_args === 'function' ?
[handler_and_args] : handler_and_args));
}
}(events, jsPDF.API.events));
} else {
API[plugin] = jsPDF.API[plugin];
}
}
}
 
//////////////////////////////////////////////////////
// continuing initialization of jsPDF Document object
//////////////////////////////////////////////////////
// Add the first page automatically
addFonts();
activeFontKey = 'F1';
_addPage(format, orientation);
 
events.publish('initialized');
return API;
}
 
/**
* jsPDF.API is a STATIC property of jsPDF class.
* jsPDF.API is an object you can add methods and properties to.
* The methods / properties you add will show up in new jsPDF objects.
*
* One property is prepopulated. It is the 'events' Object. Plugin authors can add topics,
* callbacks to this object. These will be reassigned to all new instances of jsPDF.
* Examples:
* jsPDF.API.events['initialized'] = function(){ 'this' is API object }
* jsPDF.API.events['addFont'] = function(added_font_object){ 'this' is API object }
*
* @static
* @public
* @memberOf jsPDF
* @name API
*
* @example
* jsPDF.API.mymethod = function(){
* // 'this' will be ref to internal API object. see jsPDF source
* // , so you can refer to built-in methods like so:
* // this.line(....)
* // this.text(....)
* }
* var pdfdoc = new jsPDF()
* pdfdoc.mymethod() // <- !!!!!!
*/
jsPDF.API = {events:[]};
jsPDF.version = "1.0.0-trunk";
 
if (typeof define === 'function' && define.amd) {
define('jsPDF', function() {
return jsPDF;
});
} else if (typeof module !== 'undefined' && module.exports) {
module.exports = jsPDF;
} else {
global.jsPDF = jsPDF;
}
return jsPDF;
}(typeof self !== "undefined" && self || typeof window !== "undefined" && window || this));
/base/000_base/node_modules/highcharts/lib/rgbcolor.js
@@ -0,0 +1,17 @@
/*
 
A class to parse color values
@author Stoyan Stefanov <sstoo@gmail.com>
@link http://www.phpied.com/rgb-color-parser-in-javascript/
@license Use it if you like it
*/
(function(f){function g(b){this.ok=!1;"#"==b.charAt(0)&&(b=b.substr(1,6));b=b.replace(/ /g,"");b=b.toLowerCase();var m={aliceblue:"f0f8ff",antiquewhite:"faebd7",aqua:"00ffff",aquamarine:"7fffd4",azure:"f0ffff",beige:"f5f5dc",bisque:"ffe4c4",black:"000000",blanchedalmond:"ffebcd",blue:"0000ff",blueviolet:"8a2be2",brown:"a52a2a",burlywood:"deb887",cadetblue:"5f9ea0",chartreuse:"7fff00",chocolate:"d2691e",coral:"ff7f50",cornflowerblue:"6495ed",cornsilk:"fff8dc",crimson:"dc143c",cyan:"00ffff",darkblue:"00008b",
darkcyan:"008b8b",darkgoldenrod:"b8860b",darkgray:"a9a9a9",darkgreen:"006400",darkkhaki:"bdb76b",darkmagenta:"8b008b",darkolivegreen:"556b2f",darkorange:"ff8c00",darkorchid:"9932cc",darkred:"8b0000",darksalmon:"e9967a",darkseagreen:"8fbc8f",darkslateblue:"483d8b",darkslategray:"2f4f4f",darkturquoise:"00ced1",darkviolet:"9400d3",deeppink:"ff1493",deepskyblue:"00bfff",dimgray:"696969",dodgerblue:"1e90ff",feldspar:"d19275",firebrick:"b22222",floralwhite:"fffaf0",forestgreen:"228b22",fuchsia:"ff00ff",
gainsboro:"dcdcdc",ghostwhite:"f8f8ff",gold:"ffd700",goldenrod:"daa520",gray:"808080",green:"008000",greenyellow:"adff2f",honeydew:"f0fff0",hotpink:"ff69b4",indianred:"cd5c5c",indigo:"4b0082",ivory:"fffff0",khaki:"f0e68c",lavender:"e6e6fa",lavenderblush:"fff0f5",lawngreen:"7cfc00",lemonchiffon:"fffacd",lightblue:"add8e6",lightcoral:"f08080",lightcyan:"e0ffff",lightgoldenrodyellow:"fafad2",lightgrey:"d3d3d3",lightgreen:"90ee90",lightpink:"ffb6c1",lightsalmon:"ffa07a",lightseagreen:"20b2aa",lightskyblue:"87cefa",
lightslateblue:"8470ff",lightslategray:"778899",lightsteelblue:"b0c4de",lightyellow:"ffffe0",lime:"00ff00",limegreen:"32cd32",linen:"faf0e6",magenta:"ff00ff",maroon:"800000",mediumaquamarine:"66cdaa",mediumblue:"0000cd",mediumorchid:"ba55d3",mediumpurple:"9370d8",mediumseagreen:"3cb371",mediumslateblue:"7b68ee",mediumspringgreen:"00fa9a",mediumturquoise:"48d1cc",mediumvioletred:"c71585",midnightblue:"191970",mintcream:"f5fffa",mistyrose:"ffe4e1",moccasin:"ffe4b5",navajowhite:"ffdead",navy:"000080",
oldlace:"fdf5e6",olive:"808000",olivedrab:"6b8e23",orange:"ffa500",orangered:"ff4500",orchid:"da70d6",palegoldenrod:"eee8aa",palegreen:"98fb98",paleturquoise:"afeeee",palevioletred:"d87093",papayawhip:"ffefd5",peachpuff:"ffdab9",peru:"cd853f",pink:"ffc0cb",plum:"dda0dd",powderblue:"b0e0e6",purple:"800080",red:"ff0000",rosybrown:"bc8f8f",royalblue:"4169e1",saddlebrown:"8b4513",salmon:"fa8072",sandybrown:"f4a460",seagreen:"2e8b57",seashell:"fff5ee",sienna:"a0522d",silver:"c0c0c0",skyblue:"87ceeb",slateblue:"6a5acd",
slategray:"708090",snow:"fffafa",springgreen:"00ff7f",steelblue:"4682b4",tan:"d2b48c",teal:"008080",thistle:"d8bfd8",tomato:"ff6347",turquoise:"40e0d0",violet:"ee82ee",violetred:"d02090",wheat:"f5deb3",white:"ffffff",whitesmoke:"f5f5f5",yellow:"ffff00",yellowgreen:"9acd32"},e;for(e in m)b==e&&(b=m[e]);var h=[{re:/^rgb\((\d{1,3}),\s*(\d{1,3}),\s*(\d{1,3})\)$/,example:["rgb(123, 234, 45)","rgb(255,234,245)"],process:function(a){return[parseInt(a[1]),parseInt(a[2]),parseInt(a[3])]}},{re:/^(\w{2})(\w{2})(\w{2})$/,
example:["#00ff00","336699"],process:function(a){return[parseInt(a[1],16),parseInt(a[2],16),parseInt(a[3],16)]}},{re:/^(\w{1})(\w{1})(\w{1})$/,example:["#fb0","f0f"],process:function(a){return[parseInt(a[1]+a[1],16),parseInt(a[2]+a[2],16),parseInt(a[3]+a[3],16)]}}];for(e=0;e<h.length;e++){var f=h[e].process,k=h[e].re.exec(b);k&&(channels=f(k),this.r=channels[0],this.g=channels[1],this.b=channels[2],this.ok=!0)}this.r=0>this.r||isNaN(this.r)?0:255<this.r?255:this.r;this.g=0>this.g||isNaN(this.g)?0:
255<this.g?255:this.g;this.b=0>this.b||isNaN(this.b)?0:255<this.b?255:this.b;this.toRGB=function(){return"rgb("+this.r+", "+this.g+", "+this.b+")"};this.toHex=function(){var a=this.r.toString(16),c=this.g.toString(16),d=this.b.toString(16);1==a.length&&(a="0"+a);1==c.length&&(c="0"+c);1==d.length&&(d="0"+d);return"#"+a+c+d};this.getHelpXML=function(){for(var a=[],c=0;c<h.length;c++)for(var d=h[c].example,b=0;b<d.length;b++)a[a.length]=d[b];for(var e in m)a[a.length]=e;d=document.createElement("ul");
d.setAttribute("id","rgbcolor-examples");for(c=0;c<a.length;c++)try{var f=document.createElement("li"),l=new g(a[c]),n=document.createElement("div");n.style.cssText="margin: 3px; border: 1px solid black; background:"+l.toHex()+"; color:"+l.toHex();n.appendChild(document.createTextNode("test"));var k=document.createTextNode(" "+a[c]+" -> "+l.toRGB()+" -> "+l.toHex());f.appendChild(n);f.appendChild(k);d.appendChild(f)}catch(p){}return d}}"function"===typeof define&&define.amd?define(function(){return g}):
"undefined"!==typeof module&&module.exports?module.exports=g:f.RGBColor=g;return g})("undefined"!==typeof self&&self||"undefined"!==typeof window&&window||this);
/base/000_base/node_modules/highcharts/lib/rgbcolor.src.js
@@ -0,0 +1,299 @@
/** @preserve
* A class to parse color values
* @author Stoyan Stefanov <sstoo@gmail.com>
* @link http://www.phpied.com/rgb-color-parser-in-javascript/
* @license Use it if you like it
*/
(function (global) {
function RGBColor(color_string)
{
this.ok = false;
 
// strip any leading #
if (color_string.charAt(0) == '#') { // remove # if any
color_string = color_string.substr(1,6);
}
 
color_string = color_string.replace(/ /g,'');
color_string = color_string.toLowerCase();
 
// before getting into regexps, try simple matches
// and overwrite the input
var simple_colors = {
aliceblue: 'f0f8ff',
antiquewhite: 'faebd7',
aqua: '00ffff',
aquamarine: '7fffd4',
azure: 'f0ffff',
beige: 'f5f5dc',
bisque: 'ffe4c4',
black: '000000',
blanchedalmond: 'ffebcd',
blue: '0000ff',
blueviolet: '8a2be2',
brown: 'a52a2a',
burlywood: 'deb887',
cadetblue: '5f9ea0',
chartreuse: '7fff00',
chocolate: 'd2691e',
coral: 'ff7f50',
cornflowerblue: '6495ed',
cornsilk: 'fff8dc',
crimson: 'dc143c',
cyan: '00ffff',
darkblue: '00008b',
darkcyan: '008b8b',
darkgoldenrod: 'b8860b',
darkgray: 'a9a9a9',
darkgreen: '006400',
darkkhaki: 'bdb76b',
darkmagenta: '8b008b',
darkolivegreen: '556b2f',
darkorange: 'ff8c00',
darkorchid: '9932cc',
darkred: '8b0000',
darksalmon: 'e9967a',
darkseagreen: '8fbc8f',
darkslateblue: '483d8b',
darkslategray: '2f4f4f',
darkturquoise: '00ced1',
darkviolet: '9400d3',
deeppink: 'ff1493',
deepskyblue: '00bfff',
dimgray: '696969',
dodgerblue: '1e90ff',
feldspar: 'd19275',
firebrick: 'b22222',
floralwhite: 'fffaf0',
forestgreen: '228b22',
fuchsia: 'ff00ff',
gainsboro: 'dcdcdc',
ghostwhite: 'f8f8ff',
gold: 'ffd700',
goldenrod: 'daa520',
gray: '808080',
green: '008000',
greenyellow: 'adff2f',
honeydew: 'f0fff0',
hotpink: 'ff69b4',
indianred : 'cd5c5c',
indigo : '4b0082',
ivory: 'fffff0',
khaki: 'f0e68c',
lavender: 'e6e6fa',
lavenderblush: 'fff0f5',
lawngreen: '7cfc00',
lemonchiffon: 'fffacd',
lightblue: 'add8e6',
lightcoral: 'f08080',
lightcyan: 'e0ffff',
lightgoldenrodyellow: 'fafad2',
lightgrey: 'd3d3d3',
lightgreen: '90ee90',
lightpink: 'ffb6c1',
lightsalmon: 'ffa07a',
lightseagreen: '20b2aa',
lightskyblue: '87cefa',
lightslateblue: '8470ff',
lightslategray: '778899',
lightsteelblue: 'b0c4de',
lightyellow: 'ffffe0',
lime: '00ff00',
limegreen: '32cd32',
linen: 'faf0e6',
magenta: 'ff00ff',
maroon: '800000',
mediumaquamarine: '66cdaa',
mediumblue: '0000cd',
mediumorchid: 'ba55d3',
mediumpurple: '9370d8',
mediumseagreen: '3cb371',
mediumslateblue: '7b68ee',
mediumspringgreen: '00fa9a',
mediumturquoise: '48d1cc',
mediumvioletred: 'c71585',
midnightblue: '191970',
mintcream: 'f5fffa',
mistyrose: 'ffe4e1',
moccasin: 'ffe4b5',
navajowhite: 'ffdead',
navy: '000080',
oldlace: 'fdf5e6',
olive: '808000',
olivedrab: '6b8e23',
orange: 'ffa500',
orangered: 'ff4500',
orchid: 'da70d6',
palegoldenrod: 'eee8aa',
palegreen: '98fb98',
paleturquoise: 'afeeee',
palevioletred: 'd87093',
papayawhip: 'ffefd5',
peachpuff: 'ffdab9',
peru: 'cd853f',
pink: 'ffc0cb',
plum: 'dda0dd',
powderblue: 'b0e0e6',
purple: '800080',
red: 'ff0000',
rosybrown: 'bc8f8f',
royalblue: '4169e1',
saddlebrown: '8b4513',
salmon: 'fa8072',
sandybrown: 'f4a460',
seagreen: '2e8b57',
seashell: 'fff5ee',
sienna: 'a0522d',
silver: 'c0c0c0',
skyblue: '87ceeb',
slateblue: '6a5acd',
slategray: '708090',
snow: 'fffafa',
springgreen: '00ff7f',
steelblue: '4682b4',
tan: 'd2b48c',
teal: '008080',
thistle: 'd8bfd8',
tomato: 'ff6347',
turquoise: '40e0d0',
violet: 'ee82ee',
violetred: 'd02090',
wheat: 'f5deb3',
white: 'ffffff',
whitesmoke: 'f5f5f5',
yellow: 'ffff00',
yellowgreen: '9acd32'
};
for (var key in simple_colors) {
if (color_string == key) {
color_string = simple_colors[key];
}
}
// emd of simple type-in colors
 
// array of color definition objects
var color_defs = [
{
re: /^rgb\((\d{1,3}),\s*(\d{1,3}),\s*(\d{1,3})\)$/,
example: ['rgb(123, 234, 45)', 'rgb(255,234,245)'],
process: function (bits){
return [
parseInt(bits[1]),
parseInt(bits[2]),
parseInt(bits[3])
];
}
},
{
re: /^(\w{2})(\w{2})(\w{2})$/,
example: ['#00ff00', '336699'],
process: function (bits){
return [
parseInt(bits[1], 16),
parseInt(bits[2], 16),
parseInt(bits[3], 16)
];
}
},
{
re: /^(\w{1})(\w{1})(\w{1})$/,
example: ['#fb0', 'f0f'],
process: function (bits){
return [
parseInt(bits[1] + bits[1], 16),
parseInt(bits[2] + bits[2], 16),
parseInt(bits[3] + bits[3], 16)
];
}
}
];
 
// search through the definitions to find a match
for (var i = 0; i < color_defs.length; i++) {
var re = color_defs[i].re;
var processor = color_defs[i].process;
var bits = re.exec(color_string);
if (bits) {
channels = processor(bits);
this.r = channels[0];
this.g = channels[1];
this.b = channels[2];
this.ok = true;
}
 
}
 
// validate/cleanup values
this.r = (this.r < 0 || isNaN(this.r)) ? 0 : ((this.r > 255) ? 255 : this.r);
this.g = (this.g < 0 || isNaN(this.g)) ? 0 : ((this.g > 255) ? 255 : this.g);
this.b = (this.b < 0 || isNaN(this.b)) ? 0 : ((this.b > 255) ? 255 : this.b);
 
// some getters
this.toRGB = function () {
return 'rgb(' + this.r + ', ' + this.g + ', ' + this.b + ')';
}
this.toHex = function () {
var r = this.r.toString(16);
var g = this.g.toString(16);
var b = this.b.toString(16);
if (r.length == 1) r = '0' + r;
if (g.length == 1) g = '0' + g;
if (b.length == 1) b = '0' + b;
return '#' + r + g + b;
}
 
// help
this.getHelpXML = function () {
 
var examples = new Array();
// add regexps
for (var i = 0; i < color_defs.length; i++) {
var example = color_defs[i].example;
for (var j = 0; j < example.length; j++) {
examples[examples.length] = example[j];
}
}
// add type-in colors
for (var sc in simple_colors) {
examples[examples.length] = sc;
}
 
var xml = document.createElement('ul');
xml.setAttribute('id', 'rgbcolor-examples');
for (var i = 0; i < examples.length; i++) {
try {
var list_item = document.createElement('li');
var list_color = new RGBColor(examples[i]);
var example_div = document.createElement('div');
example_div.style.cssText =
'margin: 3px; '
+ 'border: 1px solid black; '
+ 'background:' + list_color.toHex() + '; '
+ 'color:' + list_color.toHex()
;
example_div.appendChild(document.createTextNode('test'));
var list_item_value = document.createTextNode(
' ' + examples[i] + ' -> ' + list_color.toRGB() + ' -> ' + list_color.toHex()
);
list_item.appendChild(example_div);
list_item.appendChild(list_item_value);
xml.appendChild(list_item);
 
} catch(e){}
}
return xml;
 
}
 
}
if (typeof define === "function" && define.amd) {
define(function () {
return RGBColor;
});
} else if (typeof module !== "undefined" && module.exports) {
module.exports = RGBColor;
} else {
global.RGBColor = RGBColor;
}
return RGBColor;
})(typeof self !== "undefined" && self || typeof window !== "undefined" && window || this);
/base/000_base/node_modules/highcharts/lib/svg2pdf.js
@@ -0,0 +1,26 @@
/**
* Modules in this bundle
* @license
*
* svg2pdf.js:
* license: MIT (http://opensource.org/licenses/MIT)
* author: yFiles for HTML Support Team <yfileshtml@yworks.com>
* homepage: https://github.com/yWorks/svg2pdf.js#readme
* version: 1.0.5
*
* svgpath:
* license: MIT (http://opensource.org/licenses/MIT)
* maintainers: vitaly <vitaly@rcdesign.ru>
* homepage: https://github.com/fontello/svgpath#readme
* version: 2.2.1
*
* This header is generated by licensify (https://github.com/twada/licensify)
*/
!function(t){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=t();else if("function"==typeof define&&define.amd)define([],t);else{var e;e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self?self:this,e.svg2pdf=t()}}(function(){var t;return function t(e,r,a){function i(s,o){if(!r[s]){if(!e[s]){var u="function"==typeof require&&require;if(!o&&u)return u(s,!0);if(n)return n(s,!0);var c=new Error("Cannot find module '"+s+"'");throw c.code="MODULE_NOT_FOUND",c}var h=r[s]={exports:{}};e[s][0].call(h.exports,function(t){var r=e[s][1][t];return i(r||t)},h,h.exports,t,e,r,a)}return r[s].exports}for(var n="function"==typeof require&&require,s=0;s<a.length;s++)i(a[s]);return i}({1:[function(t,e,r){"use strict";e.exports=t("./lib/svgpath")},{"./lib/svgpath":6}],2:[function(t,e,r){"use strict";function a(t,e,r,a){var i=t*a-e*r<0?-1:1,n=Math.sqrt(t*t+e*e),s=Math.sqrt(t*t+e*e),o=t*r+e*a,u=o/(n*s);return u>1&&(u=1),u<-1&&(u=-1),i*Math.acos(u)}function i(t,e,r,i,n,o,u,c,h,f){var l=f*(t-r)/2+h*(e-i)/2,d=-h*(t-r)/2+f*(e-i)/2,g=u*u,p=c*c,b=l*l,x=d*d,m=g*p-g*x-p*b;m<0&&(m=0),m/=g*x+p*b,m=Math.sqrt(m)*(n===o?-1:1);var v=m*u/c*d,y=m*-c/u*l,A=f*v-h*y+(t+r)/2,w=h*v+f*y+(e+i)/2,k=(l-v)/u,M=(d-y)/c,F=(-l-v)/u,C=(-d-y)/c,S=a(1,0,k,M),I=a(k,M,F,C);return 0===o&&I>0&&(I-=s),1===o&&I<0&&(I+=s),[A,w,S,I]}function n(t,e){var r=4/3*Math.tan(e/4),a=Math.cos(t),i=Math.sin(t),n=Math.cos(t+e),s=Math.sin(t+e);return[a,i,a-i*r,i+a*r,n+s*r,s-n*r,n,s]}var s=2*Math.PI;e.exports=function(t,e,r,a,o,u,c,h,f){var l=Math.sin(f*s/360),d=Math.cos(f*s/360),g=d*(t-r)/2+l*(e-a)/2,p=-l*(t-r)/2+d*(e-a)/2;if(0===g&&0===p)return[];if(0===c||0===h)return[];c=Math.abs(c),h=Math.abs(h);var b=g*g/(c*c)+p*p/(h*h);b>1&&(c*=Math.sqrt(b),h*=Math.sqrt(b));var x=i(t,e,r,a,o,u,c,h,l,d),m=[],v=x[2],y=x[3],A=Math.max(Math.ceil(Math.abs(y)/(s/4)),1);y/=A;for(var w=0;w<A;w++)m.push(n(v,y)),v+=y;return m.map(function(t){for(var e=0;e<t.length;e+=2){var r=t[e+0],a=t[e+1];r*=c,a*=h;var i=d*r-l*a,n=l*r+d*a;t[e+0]=i+x[0],t[e+1]=n+x[1]}return t})}},{}],3:[function(t,e,r){"use strict";function a(t,e,r){if(!(this instanceof a))return new a(t,e,r);this.rx=t,this.ry=e,this.ax=r}var i=Math.PI/180;a.prototype.transform=function(t){var e=Math.cos(this.ax*i),r=Math.sin(this.ax*i),a=[this.rx*(t[0]*e+t[2]*r),this.rx*(t[1]*e+t[3]*r),this.ry*(-t[0]*r+t[2]*e),this.ry*(-t[1]*r+t[3]*e)],n=a[0]*a[0]+a[2]*a[2],s=a[1]*a[1]+a[3]*a[3],o=((a[0]-a[3])*(a[0]-a[3])+(a[2]+a[1])*(a[2]+a[1]))*((a[0]+a[3])*(a[0]+a[3])+(a[2]-a[1])*(a[2]-a[1])),u=(n+s)/2;if(o<1e-10*u)return this.rx=this.ry=Math.sqrt(u),this.ax=0,this;var c=a[0]*a[1]+a[2]*a[3];o=Math.sqrt(o);var h=u+o/2,f=u-o/2;return this.ax=Math.abs(c)<1e-10&&Math.abs(h-s)<1e-10?90:180*Math.atan(Math.abs(c)>Math.abs(h-s)?(h-n)/c:c/(h-s))/Math.PI,this.ax>=0?(this.rx=Math.sqrt(h),this.ry=Math.sqrt(f)):(this.ax+=90,this.rx=Math.sqrt(f),this.ry=Math.sqrt(h)),this},a.prototype.isDegenerate=function(){return this.rx<1e-10*this.ry||this.ry<1e-10*this.rx},e.exports=a},{}],4:[function(t,e,r){"use strict";function a(t,e){return[t[0]*e[0]+t[2]*e[1],t[1]*e[0]+t[3]*e[1],t[0]*e[2]+t[2]*e[3],t[1]*e[2]+t[3]*e[3],t[0]*e[4]+t[2]*e[5]+t[4],t[1]*e[4]+t[3]*e[5]+t[5]]}function i(){if(!(this instanceof i))return new i;this.queue=[],this.cache=null}i.prototype.matrix=function(t){return 1===t[0]&&0===t[1]&&0===t[2]&&1===t[3]&&0===t[4]&&0===t[5]?this:(this.cache=null,this.queue.push(t),this)},i.prototype.translate=function(t,e){return 0===t&&0===e||(this.cache=null,this.queue.push([1,0,0,1,t,e])),this},i.prototype.scale=function(t,e){return 1===t&&1===e||(this.cache=null,this.queue.push([t,0,0,e,0,0])),this},i.prototype.rotate=function(t,e,r){var a,i,n;return 0!==t&&(this.translate(e,r),a=t*Math.PI/180,i=Math.cos(a),n=Math.sin(a),this.queue.push([i,n,-n,i,0,0]),this.cache=null,this.translate(-e,-r)),this},i.prototype.skewX=function(t){return 0!==t&&(this.cache=null,this.queue.push([1,0,Math.tan(t*Math.PI/180),1,0,0])),this},i.prototype.skewY=function(t){return 0!==t&&(this.cache=null,this.queue.push([1,Math.tan(t*Math.PI/180),0,1,0,0])),this},i.prototype.toArray=function(){if(this.cache)return this.cache;if(!this.queue.length)return this.cache=[1,0,0,1,0,0],this.cache;if(this.cache=this.queue[0],1===this.queue.length)return this.cache;for(var t=1;t<this.queue.length;t++)this.cache=a(this.cache,this.queue[t]);return this.cache},i.prototype.calc=function(t,e,r){var a;return this.queue.length?(this.cache||(this.cache=this.toArray()),a=this.cache,[t*a[0]+e*a[2]+(r?0:a[4]),t*a[1]+e*a[3]+(r?0:a[5])]):[t,e]},e.exports=i},{}],5:[function(t,e,r){"use strict";function a(t){return 10===t||13===t||8232===t||8233===t||32===t||9===t||11===t||12===t||160===t||t>=5760&&d.indexOf(t)>=0}function i(t){switch(32|t){case 109:case 122:case 108:case 104:case 118:case 99:case 115:case 113:case 116:case 97:case 114:return!0}return!1}function n(t){return t>=48&&t<=57}function s(t){return t>=48&&t<=57||43===t||45===t||46===t}function o(t){this.index=0,this.path=t,this.max=t.length,this.result=[],this.param=0,this.err="",this.segmentStart=0,this.data=[]}function u(t){for(;t.index<t.max&&a(t.path.charCodeAt(t.index));)t.index++}function c(t){var e,r=t.index,a=r,i=t.max,s=!1,o=!1,u=!1,c=!1;if(a>=i)return void(t.err="SvgPath: missed param (at pos "+a+")");if(e=t.path.charCodeAt(a),43!==e&&45!==e||(a++,e=a<i?t.path.charCodeAt(a):0),!n(e)&&46!==e)return void(t.err="SvgPath: param should start with 0..9 or `.` (at pos "+a+")");if(46!==e){if(s=48===e,a++,e=a<i?t.path.charCodeAt(a):0,s&&a<i&&e&&n(e))return void(t.err="SvgPath: numbers started with `0` such as `09` are ilegal (at pos "+r+")");for(;a<i&&n(t.path.charCodeAt(a));)a++,o=!0;e=a<i?t.path.charCodeAt(a):0}if(46===e){for(c=!0,a++;n(t.path.charCodeAt(a));)a++,u=!0;e=a<i?t.path.charCodeAt(a):0}if(101===e||69===e){if(c&&!o&&!u)return void(t.err="SvgPath: invalid float exponent (at pos "+a+")");if(a++,e=a<i?t.path.charCodeAt(a):0,43!==e&&45!==e||a++,!(a<i&&n(t.path.charCodeAt(a))))return void(t.err="SvgPath: invalid float exponent (at pos "+a+")");for(;a<i&&n(t.path.charCodeAt(a));)a++}t.index=a,t.param=parseFloat(t.path.slice(r,a))+0}function h(t){var e,r;e=t.path[t.segmentStart],r=e.toLowerCase();var a=t.data;if("m"===r&&a.length>2&&(t.result.push([e,a[0],a[1]]),a=a.slice(2),r="l",e="m"===e?"l":"L"),"r"===r)t.result.push([e].concat(a));else for(;a.length>=l[r]&&(t.result.push([e].concat(a.splice(0,l[r]))),l[r]););}function f(t){var e,r,a,n,o=t.max;if(t.segmentStart=t.index,e=t.path.charCodeAt(t.index),!i(e))return void(t.err="SvgPath: bad command "+t.path[t.index]+" (at pos "+t.index+")");if(a=l[t.path[t.index].toLowerCase()],t.index++,u(t),t.data=[],!a)return void h(t);for(r=!1;;){for(n=a;n>0;n--){if(c(t),t.err.length)return;t.data.push(t.param),u(t),r=!1,t.index<o&&44===t.path.charCodeAt(t.index)&&(t.index++,u(t),r=!0)}if(!r){if(t.index>=t.max)break;if(!s(t.path.charCodeAt(t.index)))break}}h(t)}var l={a:7,c:6,h:1,l:2,m:2,r:4,q:4,s:4,t:2,v:1,z:0},d=[5760,6158,8192,8193,8194,8195,8196,8197,8198,8199,8200,8201,8202,8239,8287,12288,65279];e.exports=function(t){var e=new o(t),r=e.max;for(u(e);e.index<r&&!e.err.length;)f(e);return e.err.length?e.result=[]:e.result.length&&("mM".indexOf(e.result[0][0])<0?(e.err="SvgPath: string should start with `M` or `m`",e.result=[]):e.result[0][0]="M"),{err:e.err,segments:e.result}}},{}],6:[function(t,e,r){"use strict";function a(t){if(!(this instanceof a))return new a(t);var e=i(t);this.segments=e.segments,this.err=e.err,this.__stack=[]}var i=t("./path_parse"),n=t("./transform_parse"),s=t("./matrix"),o=t("./a2c"),u=t("./ellipse");a.prototype.__matrix=function(t){var e,r=this;t.queue.length&&this.iterate(function(a,i,n,s){var o,c,h,f;switch(a[0]){case"v":o=t.calc(0,a[1],!0),c=0===o[0]?["v",o[1]]:["l",o[0],o[1]];break;case"V":o=t.calc(n,a[1],!1),c=o[0]===t.calc(n,s,!1)[0]?["V",o[1]]:["L",o[0],o[1]];break;case"h":o=t.calc(a[1],0,!0),c=0===o[1]?["h",o[0]]:["l",o[0],o[1]];break;case"H":o=t.calc(a[1],s,!1),c=o[1]===t.calc(n,s,!1)[1]?["H",o[0]]:["L",o[0],o[1]];break;case"a":case"A":var l=t.toArray(),d=u(a[1],a[2],a[3]).transform(l);if(l[0]*l[3]-l[1]*l[2]<0&&(a[5]=a[5]?"0":"1"),o=t.calc(a[6],a[7],"a"===a[0]),"A"===a[0]&&a[6]===n&&a[7]===s||"a"===a[0]&&0===a[6]&&0===a[7]){c=["a"===a[0]?"l":"L",o[0],o[1]];break}c=d.isDegenerate()?["a"===a[0]?"l":"L",o[0],o[1]]:[a[0],d.rx,d.ry,d.ax,a[4],a[5],o[0],o[1]];break;case"m":f=i>0,o=t.calc(a[1],a[2],f),c=["m",o[0],o[1]];break;default:for(h=a[0],c=[h],f=h.toLowerCase()===h,e=1;e<a.length;e+=2)o=t.calc(a[e],a[e+1],f),c.push(o[0],o[1])}r.segments[i]=c},!0)},a.prototype.__evaluateStack=function(){var t,e;if(this.__stack.length){if(1===this.__stack.length)return this.__matrix(this.__stack[0]),void(this.__stack=[]);for(t=s(),e=this.__stack.length;--e>=0;)t.matrix(this.__stack[e].toArray());this.__matrix(t),this.__stack=[]}},a.prototype.toString=function(){var t,e,r=[];this.__evaluateStack();for(var a=0;a<this.segments.length;a++)e=this.segments[a][0],t=a>0&&"m"!==e&&"M"!==e&&e===this.segments[a-1][0],r=r.concat(t?this.segments[a].slice(1):this.segments[a]);return r.join(" ").replace(/ ?([achlmqrstvz]) ?/gi,"$1").replace(/ \-/g,"-").replace(/zm/g,"z m")},a.prototype.translate=function(t,e){return this.__stack.push(s().translate(t,e||0)),this},a.prototype.scale=function(t,e){return this.__stack.push(s().scale(t,e||0===e?e:t)),this},a.prototype.rotate=function(t,e,r){return this.__stack.push(s().rotate(t,e||0,r||0)),this},a.prototype.skewX=function(t){return this.__stack.push(s().skewX(t)),this},a.prototype.skewY=function(t){return this.__stack.push(s().skewY(t)),this},a.prototype.matrix=function(t){return this.__stack.push(s().matrix(t)),this},a.prototype.transform=function(t){return t.trim()?(this.__stack.push(n(t)),this):this},a.prototype.round=function(t){var e,r=0,a=0,i=0,n=0;return t=t||0,this.__evaluateStack(),this.segments.forEach(function(s){var o=s[0].toLowerCase()===s[0];switch(s[0]){case"H":case"h":return o&&(s[1]+=i),i=s[1]-s[1].toFixed(t),void(s[1]=+s[1].toFixed(t));case"V":case"v":return o&&(s[1]+=n),n=s[1]-s[1].toFixed(t),void(s[1]=+s[1].toFixed(t));case"Z":case"z":return i=r,void(n=a);case"M":case"m":return o&&(s[1]+=i,s[2]+=n),i=s[1]-s[1].toFixed(t),n=s[2]-s[2].toFixed(t),r=i,a=n,s[1]=+s[1].toFixed(t),void(s[2]=+s[2].toFixed(t));case"A":case"a":return o&&(s[6]+=i,s[7]+=n),i=s[6]-s[6].toFixed(t),n=s[7]-s[7].toFixed(t),s[1]=+s[1].toFixed(t),s[2]=+s[2].toFixed(t),s[3]=+s[3].toFixed(t+2),s[6]=+s[6].toFixed(t),void(s[7]=+s[7].toFixed(t));default:return e=s.length,o&&(s[e-2]+=i,s[e-1]+=n),i=s[e-2]-s[e-2].toFixed(t),n=s[e-1]-s[e-1].toFixed(t),void s.forEach(function(e,r){r&&(s[r]=+s[r].toFixed(t))})}}),this},a.prototype.iterate=function(t,e){var r,a,i,n=this.segments,s={},o=!1,u=0,c=0,h=0,f=0;if(e||this.__evaluateStack(),n.forEach(function(e,r){var a=t(e,r,u,c);Array.isArray(a)&&(s[r]=a,o=!0);var i=e[0]===e[0].toLowerCase();switch(e[0]){case"m":case"M":return u=e[1]+(i?u:0),c=e[2]+(i?c:0),h=u,void(f=c);case"h":case"H":return void(u=e[1]+(i?u:0));case"v":case"V":return void(c=e[1]+(i?c:0));case"z":case"Z":return u=h,void(c=f);default:u=e[e.length-2]+(i?u:0),c=e[e.length-1]+(i?c:0)}}),!o)return this;for(i=[],r=0;r<n.length;r++)if(void 0!==s[r])for(a=0;a<s[r].length;a++)i.push(s[r][a]);else i.push(n[r]);return this.segments=i,this},a.prototype.abs=function(){return this.iterate(function(t,e,r,a){var i,n=t[0],s=n.toUpperCase();if(n!==s)switch(t[0]=s,n){case"v":return void(t[1]+=a);case"a":return t[6]+=r,void(t[7]+=a);default:for(i=1;i<t.length;i++)t[i]+=i%2?r:a}},!0),this},a.prototype.rel=function(){return this.iterate(function(t,e,r,a){var i,n=t[0],s=n.toLowerCase();if(n!==s&&(0!==e||"M"!==n))switch(t[0]=s,n){case"V":return void(t[1]-=a);case"A":return t[6]-=r,void(t[7]-=a);default:for(i=1;i<t.length;i++)t[i]-=i%2?r:a}},!0),this},a.prototype.unarc=function(){return this.iterate(function(t,e,r,a){var i,n,s,u=[],c=t[0];return"A"!==c&&"a"!==c?null:("a"===c?(n=r+t[6],s=a+t[7]):(n=t[6],s=t[7]),i=o(r,a,n,s,t[4],t[5],t[1],t[2],t[3]),0===i.length?[["a"===t[0]?"l":"L",t[6],t[7]]]:(i.forEach(function(t){u.push(["C",t[2],t[3],t[4],t[5],t[6],t[7]])}),u))}),this},a.prototype.unshort=function(){var t,e,r,a,i,n=this.segments;return this.iterate(function(s,o,u,c){var h,f=s[0],l=f.toUpperCase();o&&("T"===l?(h="t"===f,r=n[o-1],"Q"===r[0]?(t=r[1]-u,e=r[2]-c):"q"===r[0]?(t=r[1]-r[3],e=r[2]-r[4]):(t=0,e=0),a=-t,i=-e,h||(a+=u,i+=c),n[o]=[h?"q":"Q",a,i,s[1],s[2]]):"S"===l&&(h="s"===f,r=n[o-1],"C"===r[0]?(t=r[3]-u,e=r[4]-c):"c"===r[0]?(t=r[3]-r[5],e=r[4]-r[6]):(t=0,e=0),a=-t,i=-e,h||(a+=u,i+=c),n[o]=[h?"c":"C",a,i,s[1],s[2],s[3],s[4]]))}),this},e.exports=a},{"./a2c":2,"./ellipse":3,"./matrix":4,"./path_parse":5,"./transform_parse":7}],7:[function(t,e,r){"use strict";var a=t("./matrix"),i={matrix:!0,scale:!0,rotate:!0,translate:!0,skewX:!0,skewY:!0};e.exports=function(t){var e,r,n=new a;return t.split(/\s*(matrix|translate|scale|rotate|skewX|skewY)\s*\(\s*(.+?)\s*\)[\s,]*/).forEach(function(t){if(t.length){if(void 0!==i[t])return void(e=t);switch(r=t.split(/[\s,]+/).map(function(t){return+t||0}),e){case"matrix":return void(6===r.length&&n.matrix(r));case"scale":return void(1===r.length?n.scale(r[0],r[0]):2===r.length&&n.scale(r[0],r[1]));case"rotate":return void(1===r.length?n.rotate(r[0],0,0):3===r.length&&n.rotate(r[0],r[1],r[2]));case"translate":return void(1===r.length?n.translate(r[0],0):2===r.length&&n.translate(r[0],r[1]));case"skewX":return void(1===r.length&&n.skewX(r[0]));case"skewY":return void(1===r.length&&n.skewY(r[0]))}}}),n}},{"./matrix":4}],8:[function(e,r,a){/**
* A class to parse color values
* @author Stoyan Stefanov <sstoo@gmail.com>
* @link http://www.phpied.com/rgb-color-parser-in-javascript/
* @license Use it if you like it
*/
!function(e){function a(t){this.ok=!1,"#"==t.charAt(0)&&(t=t.substr(1,6)),t=t.replace(/ /g,""),t=t.toLowerCase();var e={aliceblue:"f0f8ff",antiquewhite:"faebd7",aqua:"00ffff",aquamarine:"7fffd4",azure:"f0ffff",beige:"f5f5dc",bisque:"ffe4c4",black:"000000",blanchedalmond:"ffebcd",blue:"0000ff",blueviolet:"8a2be2",brown:"a52a2a",burlywood:"deb887",cadetblue:"5f9ea0",chartreuse:"7fff00",chocolate:"d2691e",coral:"ff7f50",cornflowerblue:"6495ed",cornsilk:"fff8dc",crimson:"dc143c",cyan:"00ffff",darkblue:"00008b",darkcyan:"008b8b",darkgoldenrod:"b8860b",darkgray:"a9a9a9",darkgreen:"006400",darkkhaki:"bdb76b",darkmagenta:"8b008b",darkolivegreen:"556b2f",darkorange:"ff8c00",darkorchid:"9932cc",darkred:"8b0000",darksalmon:"e9967a",darkseagreen:"8fbc8f",darkslateblue:"483d8b",darkslategray:"2f4f4f",darkturquoise:"00ced1",darkviolet:"9400d3",deeppink:"ff1493",deepskyblue:"00bfff",dimgray:"696969",dodgerblue:"1e90ff",feldspar:"d19275",firebrick:"b22222",floralwhite:"fffaf0",forestgreen:"228b22",fuchsia:"ff00ff",gainsboro:"dcdcdc",ghostwhite:"f8f8ff",gold:"ffd700",goldenrod:"daa520",gray:"808080",green:"008000",greenyellow:"adff2f",honeydew:"f0fff0",hotpink:"ff69b4",indianred:"cd5c5c",indigo:"4b0082",ivory:"fffff0",khaki:"f0e68c",lavender:"e6e6fa",lavenderblush:"fff0f5",lawngreen:"7cfc00",lemonchiffon:"fffacd",lightblue:"add8e6",lightcoral:"f08080",lightcyan:"e0ffff",lightgoldenrodyellow:"fafad2",lightgrey:"d3d3d3",lightgreen:"90ee90",lightpink:"ffb6c1",lightsalmon:"ffa07a",lightseagreen:"20b2aa",lightskyblue:"87cefa",lightslateblue:"8470ff",lightslategray:"778899",lightsteelblue:"b0c4de",lightyellow:"ffffe0",lime:"00ff00",limegreen:"32cd32",linen:"faf0e6",magenta:"ff00ff",maroon:"800000",mediumaquamarine:"66cdaa",mediumblue:"0000cd",mediumorchid:"ba55d3",mediumpurple:"9370d8",mediumseagreen:"3cb371",mediumslateblue:"7b68ee",mediumspringgreen:"00fa9a",mediumturquoise:"48d1cc",mediumvioletred:"c71585",midnightblue:"191970",mintcream:"f5fffa",mistyrose:"ffe4e1",moccasin:"ffe4b5",navajowhite:"ffdead",navy:"000080",oldlace:"fdf5e6",olive:"808000",olivedrab:"6b8e23",orange:"ffa500",orangered:"ff4500",orchid:"da70d6",palegoldenrod:"eee8aa",palegreen:"98fb98",paleturquoise:"afeeee",palevioletred:"d87093",papayawhip:"ffefd5",peachpuff:"ffdab9",peru:"cd853f",pink:"ffc0cb",plum:"dda0dd",powderblue:"b0e0e6",purple:"800080",red:"ff0000",rosybrown:"bc8f8f",royalblue:"4169e1",saddlebrown:"8b4513",salmon:"fa8072",sandybrown:"f4a460",seagreen:"2e8b57",seashell:"fff5ee",sienna:"a0522d",silver:"c0c0c0",skyblue:"87ceeb",slateblue:"6a5acd",slategray:"708090",snow:"fffafa",springgreen:"00ff7f",steelblue:"4682b4",tan:"d2b48c",teal:"008080",thistle:"d8bfd8",tomato:"ff6347",turquoise:"40e0d0",violet:"ee82ee",violetred:"d02090",wheat:"f5deb3",white:"ffffff",whitesmoke:"f5f5f5",yellow:"ffff00",yellowgreen:"9acd32"};for(var r in e)t==r&&(t=e[r]);for(var i=[{re:/^rgb\((\d{1,3}),\s*(\d{1,3}),\s*(\d{1,3})\)$/,example:["rgb(123, 234, 45)","rgb(255,234,245)"],process:function(t){return[parseInt(t[1]),parseInt(t[2]),parseInt(t[3])]}},{re:/^(\w{2})(\w{2})(\w{2})$/,example:["#00ff00","336699"],process:function(t){return[parseInt(t[1],16),parseInt(t[2],16),parseInt(t[3],16)]}},{re:/^(\w{1})(\w{1})(\w{1})$/,example:["#fb0","f0f"],process:function(t){return[parseInt(t[1]+t[1],16),parseInt(t[2]+t[2],16),parseInt(t[3]+t[3],16)]}}],n=0;n<i.length;n++){var s=i[n].re,o=i[n].process,u=s.exec(t);if(u){var c=o(u);this.r=c[0],this.g=c[1],this.b=c[2],this.ok=!0}}this.r=this.r<0||isNaN(this.r)?0:this.r>255?255:this.r,this.g=this.g<0||isNaN(this.g)?0:this.g>255?255:this.g,this.b=this.b<0||isNaN(this.b)?0:this.b>255?255:this.b,this.toRGB=function(){return"rgb("+this.r+", "+this.g+", "+this.b+")"},this.toHex=function(){var t=this.r.toString(16),e=this.g.toString(16),r=this.b.toString(16);return 1==t.length&&(t="0"+t),1==e.length&&(e="0"+e),1==r.length&&(r="0"+r),"#"+t+e+r},this.getHelpXML=function(){for(var t=new Array,r=0;r<i.length;r++)for(var n=i[r].example,s=0;s<n.length;s++)t[t.length]=n[s];for(var o in e)t[t.length]=o;var u=document.createElement("ul");u.setAttribute("id","rgbcolor-examples");for(var r=0;r<t.length;r++)try{var c=document.createElement("li"),h=new a(t[r]),f=document.createElement("div");f.style.cssText="margin: 3px; border: 1px solid black; background:"+h.toHex()+"; color:"+h.toHex(),f.appendChild(document.createTextNode("test"));var l=document.createTextNode(" "+t[r]+" -> "+h.toRGB()+" -> "+h.toHex());c.appendChild(f),c.appendChild(l),u.appendChild(c)}catch(t){}return u}}"function"==typeof t&&t.amd?t(function(){return a}):void 0!==r&&r.exports?r.exports=a:e.RGBColor=a,a}("undefined"!=typeof self&&self||"undefined"!=typeof window&&window||this)},{}],9:[function(e,r,a){!function(a){function i(t,e){var r=h(t,"font-family");r&&o.setFont(r),e&&e.ok&&o.setTextColor(e.r,e.g,e.b);var a,i=h(t,"font-weight");i&&"bold"===i&&(a="bold");var n=h(t,"font-style");n&&"italic"===n&&(a+="italic"),o.setFontType(a);var s=16,u=h(t,"font-size");u&&(s=parseFloat(u),o.setFontSize(s))}var n,s,o,u=/url\(#([^)]+)\)/,c=function(t){var e=t.getAttribute("d");s&&(e=s(e).unshort().unarc().abs().toString(),t.setAttribute("d",e));var r=t.pathSegList;if(r)return r;r=[];for(var a,i=/([a-df-zA-DF-Z])([^a-df-zA-DF-Z]*)/g;a=i.exec(e);){var n=M(a[2]),o=a[1],u="zZ".indexOf(o)>=0?0:"hHvV".indexOf(o)>=0?1:"mMlLtT".indexOf(o)>=0?2:"sSqQ".indexOf(o)>=0?4:"aA".indexOf(o)>=0?7:"cC".indexOf(o)>=0?6:-1,c=0;do{var h={pathSegTypeAsLetter:o};switch(o){case"h":case"H":h.x=n[c];break;case"v":case"V":h.y=n[c];break;case"c":case"C":h.x1=n[c+u-6],h.y1=n[c+u-5];case"s":case"S":h.x2=n[c+u-4],h.y2=n[c+u-3];case"t":case"T":case"l":case"L":case"m":case"M":h.x=n[c+u-2],h.y=n[c+u-1];break;case"q":case"Q":h.x1=n[c],h.y1=n[c+1],h.x=n[c+2],h.y=n[c+3];break;case"a":case"A":throw new Error("Cannot convert Arcs without SvgPath package")}r.push(h),c+=u}while(c<n.length)}return r.getItem=function(t){return this[t]},r.numberOfItems=r.length,r},h=function(t,e,r){return r=r||e,t.getAttribute(e)||t.style[r]},f=function(t,e){return e.split(",").indexOf(t.tagName.toLowerCase())>=0},l=function(t,e){for(var r=[],a=0;a<t.childNodes.length;a++){var i=t.childNodes[a];"#"!==i.nodeName.charAt(0)&&r.push(i)}for(a=0;a<r.length;a++)e(a,r[a])},d=function(t,e){return Math.atan2(e[1]-t[1],e[0]-t[0])},g=function(t,e){var r=e[0]-t[0],a=e[1]-t[1];return[t[0]+2*r,t[1]+2*a]},p=function(t,e){return[2/3*(e[0]-t[0])+t[0],2/3*(e[1]-t[1])+t[1]]},b=function(t,e,r,a,i){var n=r.getItem(t-1);return t>0&&("C"===n.pathSegTypeAsLetter||"S"===n.pathSegTypeAsLetter)?g([n.x2,n.y2],e):t>0&&("c"===n.pathSegTypeAsLetter||"s"===n.pathSegTypeAsLetter)?g([n.x2+a,n.y2+i],e):[e[0],e[1]]},x=function(t){this.prefix=t,this.id=0,this.nextChild=function(){return new x("_"+this.id+++"_"+this.get())},this.get=function(){return this.prefix}},m=function(t,e){for(var r=/_\d+_/;!e[t]&&r.exec(t);)t=t.replace(r,"");return e[t]},v=function(t){return t.replace(/[\n\s\r]+/," ").trim()},y=function(t){var e={};for(var r in t)t.hasOwnProperty(r)&&(e[r]=t[r]);return e},A=function(t){var e,r,a,i,n,s,u,c,h=o.unitMatrix;if(f(t,"svg,g"))c=parseFloat(t.getAttribute("x"))||0,u=parseFloat(t.getAttribute("y"))||0,s=t.getAttribute("viewBox"),s?(n=M(s),i=n[2]-n[0],a=n[3]-n[1],r=parseFloat(t.getAttribute("width"))||i,e=parseFloat(t.getAttribute("height"))||a,h=new o.Matrix(r/i,0,0,e/a,c-n[0],u-n[1])):h=new o.Matrix(1,0,0,1,c,u);else if(f(t,"marker"))if(c=-parseFloat(t.getAttribute("refX"))||0,u=-parseFloat(t.getAttribute("refY"))||0,s=t.getAttribute("viewBox")){n=M(s),i=n[2]-n[0],a=n[3]-n[1],r=parseFloat(t.getAttribute("markerWidth"))||i,e=parseFloat(t.getAttribute("markerHeight"))||a;var l=new o.Matrix(r/i,0,0,e/a,0,0),d=new o.Matrix(1,0,0,1,c,u);h=o.matrixMult(d,l)}else h=new o.Matrix(1,0,0,1,c,u);var g=t.getAttribute("transform");return g?o.matrixMult(h,k(g)):h},w=function(t){for(var e=M(t),r=[],a=0;a<e.length-1;a+=2){var i=e[a],n=e[a+1];r.push([i,n])}return r},k=function(t){if(!t)return o.unitMatrix;for(var e,r=/^\s*matrix\(([^\)]+)\)\s*/,a=/^\s*translate\(([^\)]+)\)\s*/,i=/^\s*rotate\(([^\)]+)\)\s*/,n=/^\s*scale\(([^\)]+)\)\s*/,s=/^\s*skewX\(([^\)]+)\)\s*/,u=/^\s*skewY\(([^\)]+)\)\s*/,c=o.unitMatrix;t.length>0;){var h=r.exec(t);if(h&&(e=M(h[1]),c=o.matrixMult(new o.Matrix(e[0],e[1],e[2],e[3],e[4],e[5]),c),t=t.substr(h[0].length)),h=i.exec(t)){e=M(h[1]);var f=Math.PI*e[0]/180;if(c=o.matrixMult(new o.Matrix(Math.cos(f),Math.sin(f),-Math.sin(f),Math.cos(f),0,0),c),e[1]&&e[2]){var l=new o.Matrix(1,0,0,1,e[1],e[2]),d=new o.Matrix(1,0,0,1,-e[1],-e[2]);c=o.matrixMult(d,o.matrixMult(c,l))}t=t.substr(h[0].length)}h=a.exec(t),h&&(e=M(h[1]),c=o.matrixMult(new o.Matrix(1,0,0,1,e[0],e[1]||0),c),t=t.substr(h[0].length)),h=n.exec(t),h&&(e=M(h[1]),e[1]||(e[1]=e[0]),c=o.matrixMult(new o.Matrix(e[0],0,0,e[1],0,0),c),t=t.substr(h[0].length)),h=s.exec(t),h&&(e=parseFloat(h[1]),c=o.matrixMult(new o.Matrix(1,0,Math.tan(e),1,0,0),c),t=t.substr(h[0].length)),h=u.exec(t),h&&(e=parseFloat(h[1]),c=o.matrixMult(new o.Matrix(1,Math.tan(e),0,1,0,0),c),t=t.substr(h[0].length))}return c},M=function(t){for(var e,r=[],a=/[+-]?(?:(?:\d+\.?\d*)|(?:\d*\.?\d+))(?:[eE][+-]?\d+)?/g;e=a.exec(t);)r.push(parseFloat(e[0]));return r},F=function(t){var e=/\s*rgba\(((?:[^,\)]*,){3}[^,\)]*)\)\s*/.exec(t);if(e){var r=M(e[1]),a=new n("rgb("+r.slice(0,3).join(",")+")");return a.a=r[3],a}return new n(t)},C=function(t,e){var r=t[0],a=t[1];return[e.a*r+e.c*a+e.e,e.b*r+e.d*a+e.f]},S=function(t){var e,r,a,i,n,s,o,u,d=parseFloat;if(f(t,"polygon")){var g=w(t.getAttribute("points"));for(r=Number.POSITIVE_INFINITY,a=Number.POSITIVE_INFINITY,i=Number.NEGATIVE_INFINITY,n=Number.NEGATIVE_INFINITY,e=0;e<g.length;e++){var x=g[e];r=Math.min(r,x[0]),i=Math.max(i,x[0]),a=Math.min(a,x[1]),n=Math.max(n,x[1])}u=[r,a,i-r,n-a]}else if(f(t,"path")){var m=c(t);r=Number.POSITIVE_INFINITY,a=Number.POSITIVE_INFINITY,i=Number.NEGATIVE_INFINITY,n=Number.NEGATIVE_INFINITY;var v,y,A,k,F,C,I,_=0,T=0;for(e=0;e<m.numberOfItems;e++){var q=m.getItem(e),L=q.pathSegTypeAsLetter;switch(L){case"H":A=q.x,k=T;break;case"h":A=q.x+_,k=T;break;case"V":A=_,k=q.y;break;case"v":A=_,k=q.y+T;break;case"C":F=[q.x1,q.y1],C=[q.x2,q.y2],I=[q.x,q.y];break;case"c":F=[q.x1+_,q.y1+T],C=[q.x2+_,q.y2+T],I=[q.x+_,q.y+T];break;case"S":F=b(e,[_,T],m,v,y),C=[q.x2,q.y2],I=[q.x,q.y];break;case"s":F=b(e,[_,T],m,v,y),C=[q.x2+_,q.y2+T],I=[q.x+_,q.y+T];break;case"Q":d=[q.x1,q.y1],F=p([_,T],d),C=p([q.x,q.y],d),I=[q.x,q.y];break;case"q":d=[q.x1+_,q.y1+T],F=p([_,T],d),C=p([_+q.x,T+q.y],d),I=[q.x+_,q.y+T];break;case"T":F=b(e,[_,T],m,v,y),F=p([_,T],d),C=p([q.x,q.y],d),I=[q.x,q.y];break;case"t":d=b(e,[_,T],m,v,y),F=p([_,T],d),C=p([_+q.x,T+q.y],d),I=[q.x+_,q.y+T]}"sScCqQtT".indexOf(L)>=0&&(v=_,y=T),"MLCSQT".indexOf(L)>=0?(_=q.x,T=q.y):"mlcsqt".indexOf(L)>=0?(_=q.x+_,T=q.y+T):"zZ".indexOf(L)<0&&(_=A,T=k),"CSQTcsqt".indexOf(L)>=0?(r=Math.min(r,_,F[0],C[0],I[0]),i=Math.max(i,_,F[0],C[0],I[0]),a=Math.min(a,T,F[1],C[1],I[1]),n=Math.max(n,T,F[1],C[1],I[1])):(r=Math.min(r,_),i=Math.max(i,_),a=Math.min(a,T),n=Math.max(n,T))}u=[r,a,i-r,n-a]}else{if(f(t,"svg"))return s=t.getAttribute("viewBox"),s&&(o=M(s)),[d(t.getAttribute("x"))||o&&o[0]||0,d(t.getAttribute("y"))||o&&o[1]||0,d(t.getAttribute("width"))||o&&o[2]||0,d(t.getAttribute("height"))||o&&o[3]||0];if(f(t,"g"))u=[0,0,0,0],l(t,function(t,e){var r=S(e);u=[Math.min(u[0],r[0]),Math.min(u[1],r[1]),Math.max(u[0]+u[2],r[0]+r[2])-Math.min(u[0],r[0]),Math.max(u[1]+u[3],r[1]+r[3])-Math.min(u[1],r[1])]});else{if(f(t,"marker"))return s=t.getAttribute("viewBox"),s&&(o=M(s)),[o&&o[0]||0,o&&o[1]||0,o&&o[2]||d(t.getAttribute("marker-width"))||0,o&&o[3]||d(t.getAttribute("marker-height"))||0];if(f(t,"pattern"))return[d(t.getAttribute("x"))||0,d(t.getAttribute("y"))||0,d(t.getAttribute("width"))||0,d(t.getAttribute("height"))||0];var N=d(t.getAttribute("x1"))||d(t.getAttribute("x"))||d(t.getAttribute("cx")-d(t.getAttribute("r")))||0,O=d(t.getAttribute("x2"))||N+d(t.getAttribute("width"))||d(t.getAttribute("cx"))+d(t.getAttribute("r"))||0,P=d(t.getAttribute("y1"))||d(t.getAttribute("y"))||d(t.getAttribute("cy"))-d(t.getAttribute("r"))||0,E=d(t.getAttribute("y2"))||P+d(t.getAttribute("height"))||d(t.getAttribute("cy"))+d(t.getAttribute("r"))||0;u=[Math.min(N,O),Math.min(P,E),Math.max(N,O)-Math.min(N,O),Math.max(P,E)-Math.min(P,E)]}}if(!f(t,"marker,svg,g")){var G=h(t,"stroke-width")||1;return h(t,"stroke-miterlimit")&&(G*=.5/Math.sin(Math.PI/12)),[u[0]-G,u[1]-G,u[2]+2*G,u[3]+2*G]}return u},I=function(t,e,r,a,i){for(var n=w(t.getAttribute("points")),s=[{op:"m",c:C(n[0],e)}],u=1;u<n.length;u++){var c=n[u],h=C(c,e);s.push({op:"l",c:h})}s.push({op:"h"}),o.path(s,r,a,i)},_=function(t){var e=t.getAttribute("xlink:href")||t.getAttribute("href"),r=new Image;r.src=e;var a=document.createElement("canvas"),i=parseFloat(t.getAttribute("width")),n=parseFloat(t.getAttribute("height")),s=parseFloat(t.getAttribute("x")||0),u=parseFloat(t.getAttribute("y")||0);a.width=i,a.height=n;var c=a.getContext("2d");c.fillStyle="#fff",c.fillRect(0,0,i,n),c.drawImage(r,0,0,i,n);var h=a.toDataURL("image/jpeg");o.addImage(h,"jpeg",s,u,i,n)},T=function(t,e,r,a,i,n){var s=c(t),h=t.getAttribute("marker-end"),f=t.getAttribute("marker-start"),l=t.getAttribute("marker-mid"),g=function(t,e){for(var r,a,i,n,u,c,g,x,m,v,y=0,A=0,w=y,k=A,M=[],F=[],S=0,I=function(t,r,a){var i,n=Math.cos(t),s=Math.sin(t);i=new o.Matrix(n,s,-s,n,r[0],r[1]),F.push({type:a,tf:o.matrixMult(i,e)})},_=0;_<s.numberOfItems;_++){var T=s.getItem(_),q=T.pathSegTypeAsLetter;switch(q){case"M":w=y,k=A,u=[T.x,T.y],m="m";break;case"m":w=y,k=A,u=[T.x+y,T.y+A],m="m";break;case"L":u=[T.x,T.y],m="l";break;case"l":u=[T.x+y,T.y+A],m="l";break;case"H":u=[T.x,A],m="l",i=T.x,n=A;break;case"h":u=[T.x+y,A],m="l",i=T.x+y,n=A;break;case"V":u=[y,T.y],m="l",i=y,n=T.y;break;case"v":u=[y,T.y+A],m="l",i=y,n=T.y+A;break;case"C":g=[T.x1,T.y1],x=[T.x2,T.y2],u=[T.x,T.y];break;case"c":g=[T.x1+y,T.y1+A],x=[T.x2+y,T.y2+A],u=[T.x+y,T.y+A];break;case"S":g=b(_,[y,A],s,r,a),x=[T.x2,T.y2],u=[T.x,T.y];break;case"s":g=b(_,[y,A],s,r,a),x=[T.x2+y,T.y2+A],u=[T.x+y,T.y+A];break;case"Q":c=[T.x1,T.y1],g=p([y,A],c),x=p([T.x,T.y],c),u=[T.x,T.y];break;case"q":c=[T.x1+y,T.y1+A],g=p([y,A],c),x=p([y+T.x,A+T.y],c),u=[T.x+y,T.y+A];break;case"T":g=b(_,[y,A],s,r,a),g=p([y,A],c),x=p([T.x,T.y],c),u=[T.x,T.y];break;case"t":c=b(_,[y,A],s,r,a),g=p([y,A],c),x=p([y+T.x,A+T.y],c),u=[T.x+y,T.y+A];break;case"Z":case"z":y=w,A=k,M.push({op:"h"})}var L=f&&(1===_||"mM".indexOf(q)<0&&"mM".indexOf(s.getItem(_-1).pathSegTypeAsLetter)>=0),N=h&&(_===s.numberOfItems-1||"mM".indexOf(q)<0&&"mM".indexOf(s.getItem(_+1).pathSegTypeAsLetter)>=0),O=l&&_>0&&!(1===_&&"mM".indexOf(s.getItem(_-1).pathSegTypeAsLetter)>=0);if("sScCqQtT".indexOf(q)>=0)L&&I(d([y,A],g),[y,A],"start"),N&&I(d(x,u),u,"end"),O&&(v=d([y,A],g),v="mM".indexOf(s.getItem(_-1).pathSegTypeAsLetter)>=0?v:.5*(S+v),I(v,[y,A],"mid")),S=d(x,u),r=y,a=A,g=C(g,e),x=C(x,e),c=C(u,e),M.push({op:"c",c:[g[0],g[1],x[0],x[1],c[0],c[1]]});else if("lLhHvVmM".indexOf(q)>=0){if(v=d([y,A],u),L&&I(v,[y,A],"start"),N&&I(v,u,"end"),O){var P="mM".indexOf(q)>=0?S:"mM".indexOf(s.getItem(_-1).pathSegTypeAsLetter)>=0?v:.5*(S+v);I(P,[y,A],"mid")}S=v,c=C(u,e),M.push({op:m,c:c})}"MLCSQT".indexOf(q)>=0?(y=T.x,A=T.y):"mlcsqt".indexOf(q)>=0?(y=T.x+y,A=T.y+A):"zZ".indexOf(q)<0&&(y=i,A=n)}return{lines:M,markers:F}}(0,e);if(h||f||l)for(var x=0;x<g.markers.length;x++){var m,v=g.markers[x];switch(v.type){case"start":m=r.get()+u.exec(f)[1];break;case"end":m=r.get()+u.exec(h)[1];break;case"mid":m=r.get()+u.exec(l)[1]}o.doFormObject(m,v.tf)}g.lines.length>0&&o.path(g.lines,a,i,n)},q=function(t,e,r){var a=t.getAttribute("href")||t.getAttribute("xlink:href");if(a){var i=o.getFormObject(r.get()+a.substring(1)),n=t.getAttribute("x")||0,s=t.getAttribute("y")||0,u=t.getAttribute("width")||i.width,c=t.getAttribute("height")||i.height,h=new o.Matrix(u/i.width||0,0,0,c/i.height||0,n,s);h=o.matrixMult(h,e),o.doFormObject(r.get()+a.substring(1),h)}},L=function(t,e){var r=C([parseFloat(t.getAttribute("x1")),parseFloat(t.getAttribute("y1"))],e),a=C([parseFloat(t.getAttribute("x2")),parseFloat(t.getAttribute("y2"))],e);o.line(r[0],r[1],a[0],a[1])},N=function(t,e,r,a){o.roundedRect(parseFloat(t.getAttribute("x"))||0,parseFloat(t.getAttribute("y"))||0,parseFloat(t.getAttribute("width")),parseFloat(t.getAttribute("height")),parseFloat(t.getAttribute("rx"))||0,parseFloat(t.getAttribute("ry"))||0,e,r,a)},O=function(t,e,r,a){o.ellipse(parseFloat(t.getAttribute("cx"))||0,parseFloat(t.getAttribute("cy"))||0,parseFloat(t.getAttribute("rx")),parseFloat(t.getAttribute("ry")),e,r,a)},P=function(t,e,r,a){var i=parseFloat(t.getAttribute("r"))||0;o.ellipse(parseFloat(t.getAttribute("cx"))||0,parseFloat(t.getAttribute("cy"))||0,i,i,e,r,a)},E=function(t,e){switch(h(t,"text-transform")){case"uppercase":return e.toUpperCase();case"lowercase":return e.toLowerCase();default:return e}},G=function(t,e,r,a){o.saveGraphicsState(),i(t,a);var s=function(t,e){var r;return(r=t&&t.toString().match(/^([\-0-9.]+)em$/))?parseFloat(r[1])*e:(r=t&&t.toString().match(/^([\-0-9.]+)(px|)$/),r?parseFloat(r[1]):0)},u=document.createElementNS("http://www.w3.org/2000/svg","svg");u.appendChild(t),u.setAttribute("visibility","hidden"),document.body.appendChild(u);var c,d,g=t.getBBox(),p=0,b=h(t,"text-anchor");b&&(p=function(t,e){var r=0;switch(t){case"end":r=e;break;case"middle":r=e/2}return r}(b,g.width));var x=o.getFontSize(),m=s(t.getAttribute("x"),x),y=s(t.getAttribute("y"),x),A=o.matrixMult(new o.Matrix(1,0,0,1,m,y),e);c=s(t.getAttribute("dx"),x),d=s(t.getAttribute("dy"),x),0===t.childElementCount?o.text(c-p,d,E(t,v(t.textContent)),void 0,A):l(t,function(e,r){if(r.textContent&&!f(r,"title,desc,metadata")){o.saveGraphicsState();var a=h(r,"fill");i(r,a&&new n(a));var s=r.getExtentOfChar(0);o.text(s.x-m,s.y+.7*s.height-y,E(t,v(r.textContent)),void 0,A),o.restoreGraphicsState()}}),document.body.removeChild(u),o.restoreGraphicsState()},j=function(t,e,r,a,i){l(t,function(t,n){"defs"===n.tagName.toLowerCase()&&(B(n,e,r,a,i),n.parentNode.removeChild(n))})},V=function(t,e,r,a,i){var n=a.nextChild(),s=y(r);j(t,e,s,n,i),Y(t,e,s,n,i)},Y=function(t,e,r,a,i){l(t,function(t,n){B(n,e,r,a,i)})},z=function(t,e,r,a,i){var s,u=[],c=0,f=!1;l(t,function(t,e){if("stop"===e.tagName.toLowerCase()){var r=new n(h(e,"stop-color"));u.push({offset:parseFloat(e.getAttribute("offset")),color:[r.r,r.g,r.b]});var a=h(e,"stop-opacity");a&&1!=a&&(c+=parseFloat(a),f=!0)}}),f&&(s=new o.GState({opacity:c/r.length}));var d=new o.ShadingPattern(e,r,u,s),g=i.get()+t.getAttribute("id");o.addShadingPattern(g,d),a[g]=t},H=function(t,e,r){var a=r.get()+t.getAttribute("id");e[a]=t;var i=S(t),n=new o.TilingPattern([i[0],i[1],i[0]+i[2],i[1]+i[3]],i[2],i[3],null,A(t));o.beginTilingPattern(n),Y(t,o.unitMatrix,e,r,!1),o.endTilingPattern(a,n)},B=function(t,e,r,a,s){function c(){p=new n("rgb(0, 0, 0)"),g=!0,b="F"}var l,d,g=!1,p=null,b=null,x=null,v=null,y=s&&!f(t,"lineargradient,radialgradient,pattern");if(y?(l=A(t),d=S(t),o.beginFormObject(d[0],d[1],d[2],d[3],l),l=o.unitMatrix,s=!1):(l=o.matrixMult(A(t),e),o.saveGraphicsState()),f(t,"g,path,rect,text,ellipse,line,circle,polygon")){var w=h(t,"fill");if(w){var C=u.exec(w);if(C){x=a.get()+C[1];var E=m(x,r);if(E&&f(E,"lineargradient,radialgradient")){var B=l;if(!E.hasAttribute("gradientUnits")||"objectboundingbox"===E.getAttribute("gradientUnits").toLowerCase()){d||(d=S(t)),B=new o.Matrix(d[2],0,0,d[3],d[0],d[1]);var U=A(t);B=o.matrixMult(B,U)}var Q=k(E.getAttribute("gradientTransform"));v=o.matrixMult(Q,B)}else if(E&&f(E,"pattern")){var D,X,Z,R,$;v={};var W=o.unitMatrix;E.hasAttribute("patternUnits")&&"objectboundingbox"!==E.getAttribute("patternUnits").toLowerCase()||(d||(d=S(t)),W=new o.Matrix(1,0,0,1,d[0],d[1]),D=S(E),$=D[0]*d[0],X=D[1]*d[1],Z=D[2]*d[2],R=D[3]*d[3],v.boundingBox=[$,X,$+Z,X+R],v.xStep=Z,v.yStep=R);var J=o.unitMatrix;E.hasAttribute("patternContentUnits")&&"objectboundingbox"===E.getAttribute("patternContentUnits").toLowerCase()&&(d||(d=S(t)),J=new o.Matrix(d[2],0,0,d[3],0,0),D=v.boundingBox||S(E),$=D[0]/d[0],X=D[1]/d[1],Z=D[2]/d[2],R=D[3]/d[3],v.boundingBox=[$,X,$+Z,X+R],v.xStep=Z,v.yStep=R),v.matrix=o.matrixMult(o.matrixMult(J,W),l),b="F"}else x=E=null,c()}else p=F(w),p.ok?(g=!0,b="F"):b=null}else c();var K=1,tt=t.getAttribute("opacity")||t.getAttribute("fill-opacity");tt&&(K*=parseFloat(tt)),p&&"number"==typeof p.a&&(K*=p.a),o.setGState(new o.GState({opacity:K}))}if(f(t,"g,path,rect,ellipse,line,circle,polygon")){g&&o.setFillColor(p.r,p.g,p.b);var et=t.getAttribute("stroke");if(et){var rt;t.hasAttribute("stroke-width")&&(rt=Math.abs(parseFloat(t.getAttribute("stroke-width"))),o.setLineWidth(rt));var at=new n(et);at.ok&&(o.setDrawColor(at.r,at.g,at.b),0!==rt&&(b=(b||"")+"D")),t.hasAttribute("stroke-linecap")&&o.setLineCap(t.getAttribute("stroke-linecap")),t.hasAttribute("stroke-linejoin")&&o.setLineJoin(t.getAttribute("stroke-linejoin")),t.hasAttribute("stroke-dasharray")&&o.setLineDashPattern(M(t.getAttribute("stroke-dasharray")),parseInt(t.getAttribute("stroke-dashoffset"))||0),t.hasAttribute("stroke-miterlimit")&&o.setLineMiterLimit(parseFloat(t.getAttribute("stroke-miterlimit")))}}switch(i(t,p),t.tagName.toLowerCase()){case"svg":V(t,l,r,a,s);break;case"g":j(t,l,r,a,s);case"a":case"marker":Y(t,l,r,a,s);break;case"defs":Y(t,l,r,a,!0);break;case"use":q(t,l,a);break;case"line":L(t,l);break;case"rect":o.setCurrentTransformationMatrix(l),N(t,b,x,v);break;case"ellipse":o.setCurrentTransformationMatrix(l),O(t,b,x,v);break;case"circle":o.setCurrentTransformationMatrix(l),P(t,b,x,v);break;case"text":G(t,l,0,p);break;case"path":T(t,l,a,b,x,v);break;case"polygon":I(t,l,b,x,v);break;case"image":o.setCurrentTransformationMatrix(l),_(t);break;case"lineargradient":z(t,"axial",[t.getAttribute("x1"),t.getAttribute("y1"),t.getAttribute("x2"),t.getAttribute("y2")],r,a);break;case"radialgradient":z(t,"radial",[t.getAttribute("fx")||t.getAttribute("cx"),t.getAttribute("fy")||t.getAttribute("cy"),0,t.getAttribute("cx")||0,t.getAttribute("cy")||0,t.getAttribute("r")||0],r,a);break;case"pattern":H(t,r,a)}y?o.endFormObject(a.get()+t.getAttribute("id")):o.restoreGraphicsState()},U=function(t,e,r){o=e;var a=r.scale||1,i=r.xOffset||0,n=r.yOffset||0;return o.saveGraphicsState(),o.setCurrentTransformationMatrix(new o.Matrix(a,0,0,a,i,n)),B(t.cloneNode(!0),o.unitMatrix,{},new x(""),!1),o.restoreGraphicsState(),o};"function"==typeof t&&t.amd?t(["./rgbcolor","SvgPath"],function(t,e){return n=t,s=e,U}):void 0!==r&&r.exports?(n=e("./rgbcolor.js"),s=e("SvgPath"),r.exports=U):(s=a.SvgPath,n=a.RGBColor,a.svg2pdf=U,a.svgElementToPdf=U),U}("undefined"!=typeof self&&self||"undefined"!=typeof window&&window||this)},{"./rgbcolor.js":8,SvgPath:1}]},{},[9])(9)});
//# sourceMappingURL=svg2pdf.min.js.map
/base/000_base/node_modules/highcharts/lib/svg2pdf.src.js
@@ -0,0 +1,3244 @@
/**
* Modules in this bundle
* @license
*
* svg2pdf.js:
* license: MIT (http://opensource.org/licenses/MIT)
* author: yFiles for HTML Support Team <yfileshtml@yworks.com>
* homepage: https://github.com/yWorks/svg2pdf.js#readme
* version: 1.0.5
*
* svgpath:
* license: MIT (http://opensource.org/licenses/MIT)
* maintainers: vitaly <vitaly@rcdesign.ru>
* homepage: https://github.com/fontello/svgpath#readme
* version: 2.2.1
*
* This header is generated by licensify (https://github.com/twada/licensify)
*/
(function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.svg2pdf = f()}})(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){
'use strict';
 
module.exports = require('./lib/svgpath');
 
},{"./lib/svgpath":6}],2:[function(require,module,exports){
// Convert an arc to a sequence of cubic bézier curves
//
'use strict';
 
 
var TAU = Math.PI * 2;
 
 
/* eslint-disable space-infix-ops */
 
// Calculate an angle between two vectors
//
function vector_angle(ux, uy, vx, vy) {
var sign = (ux * vy - uy * vx < 0) ? -1 : 1;
var umag = Math.sqrt(ux * ux + uy * uy);
var vmag = Math.sqrt(ux * ux + uy * uy);
var dot = ux * vx + uy * vy;
var div = dot / (umag * vmag);
 
// rounding errors, e.g. -1.0000000000000002 can screw up this
if (div > 1.0) { div = 1.0; }
if (div < -1.0) { div = -1.0; }
 
return sign * Math.acos(div);
}
 
 
// Convert from endpoint to center parameterization,
// see http://www.w3.org/TR/SVG11/implnote.html#ArcImplementationNotes
//
// Return [cx, cy, theta1, delta_theta]
//
function get_arc_center(x1, y1, x2, y2, fa, fs, rx, ry, sin_phi, cos_phi) {
// Step 1.
//
// Moving an ellipse so origin will be the middlepoint between our two
// points. After that, rotate it to line up ellipse axes with coordinate
// axes.
//
var x1p = cos_phi*(x1-x2)/2 + sin_phi*(y1-y2)/2;
var y1p = -sin_phi*(x1-x2)/2 + cos_phi*(y1-y2)/2;
 
var rx_sq = rx * rx;
var ry_sq = ry * ry;
var x1p_sq = x1p * x1p;
var y1p_sq = y1p * y1p;
 
// Step 2.
//
// Compute coordinates of the centre of this ellipse (cx', cy')
// in the new coordinate system.
//
var radicant = (rx_sq * ry_sq) - (rx_sq * y1p_sq) - (ry_sq * x1p_sq);
 
if (radicant < 0) {
// due to rounding errors it might be e.g. -1.3877787807814457e-17
radicant = 0;
}
 
radicant /= (rx_sq * y1p_sq) + (ry_sq * x1p_sq);
radicant = Math.sqrt(radicant) * (fa === fs ? -1 : 1);
 
var cxp = radicant * rx/ry * y1p;
var cyp = radicant * -ry/rx * x1p;
 
// Step 3.
//
// Transform back to get centre coordinates (cx, cy) in the original
// coordinate system.
//
var cx = cos_phi*cxp - sin_phi*cyp + (x1+x2)/2;
var cy = sin_phi*cxp + cos_phi*cyp + (y1+y2)/2;
 
// Step 4.
//
// Compute angles (theta1, delta_theta).
//
var v1x = (x1p - cxp) / rx;
var v1y = (y1p - cyp) / ry;
var v2x = (-x1p - cxp) / rx;
var v2y = (-y1p - cyp) / ry;
 
var theta1 = vector_angle(1, 0, v1x, v1y);
var delta_theta = vector_angle(v1x, v1y, v2x, v2y);
 
if (fs === 0 && delta_theta > 0) {
delta_theta -= TAU;
}
if (fs === 1 && delta_theta < 0) {
delta_theta += TAU;
}
 
return [ cx, cy, theta1, delta_theta ];
}
 
//
// Approximate one unit arc segment with bézier curves,
// see http://math.stackexchange.com/questions/873224
//
function approximate_unit_arc(theta1, delta_theta) {
var alpha = 4/3 * Math.tan(delta_theta/4);
 
var x1 = Math.cos(theta1);
var y1 = Math.sin(theta1);
var x2 = Math.cos(theta1 + delta_theta);
var y2 = Math.sin(theta1 + delta_theta);
 
return [ x1, y1, x1 - y1*alpha, y1 + x1*alpha, x2 + y2*alpha, y2 - x2*alpha, x2, y2 ];
}
 
module.exports = function a2c(x1, y1, x2, y2, fa, fs, rx, ry, phi) {
var sin_phi = Math.sin(phi * TAU / 360);
var cos_phi = Math.cos(phi * TAU / 360);
 
// Make sure radii are valid
//
var x1p = cos_phi*(x1-x2)/2 + sin_phi*(y1-y2)/2;
var y1p = -sin_phi*(x1-x2)/2 + cos_phi*(y1-y2)/2;
 
if (x1p === 0 && y1p === 0) {
// we're asked to draw line to itself
return [];
}
 
if (rx === 0 || ry === 0) {
// one of the radii is zero
return [];
}
 
 
// Compensate out-of-range radii
//
rx = Math.abs(rx);
ry = Math.abs(ry);
 
var lambda = (x1p * x1p) / (rx * rx) + (y1p * y1p) / (ry * ry);
if (lambda > 1) {
rx *= Math.sqrt(lambda);
ry *= Math.sqrt(lambda);
}
 
 
// Get center parameters (cx, cy, theta1, delta_theta)
//
var cc = get_arc_center(x1, y1, x2, y2, fa, fs, rx, ry, sin_phi, cos_phi);
 
var result = [];
var theta1 = cc[2];
var delta_theta = cc[3];
 
// Split an arc to multiple segments, so each segment
// will be less than τ/4 (= 90°)
//
var segments = Math.max(Math.ceil(Math.abs(delta_theta) / (TAU / 4)), 1);
delta_theta /= segments;
 
for (var i = 0; i < segments; i++) {
result.push(approximate_unit_arc(theta1, delta_theta));
theta1 += delta_theta;
}
 
// We have a bezier approximation of a unit circle,
// now need to transform back to the original ellipse
//
return result.map(function (curve) {
for (var i = 0; i < curve.length; i += 2) {
var x = curve[i + 0];
var y = curve[i + 1];
 
// scale
x *= rx;
y *= ry;
 
// rotate
var xp = cos_phi*x - sin_phi*y;
var yp = sin_phi*x + cos_phi*y;
 
// translate
curve[i + 0] = xp + cc[0];
curve[i + 1] = yp + cc[1];
}
 
return curve;
});
};
 
},{}],3:[function(require,module,exports){
'use strict';
 
/* eslint-disable space-infix-ops */
 
// The precision used to consider an ellipse as a circle
//
var epsilon = 0.0000000001;
 
// To convert degree in radians
//
var torad = Math.PI / 180;
 
// Class constructor :
// an ellipse centred at 0 with radii rx,ry and x - axis - angle ax.
//
function Ellipse(rx, ry, ax) {
if (!(this instanceof Ellipse)) { return new Ellipse(rx, ry, ax); }
this.rx = rx;
this.ry = ry;
this.ax = ax;
}
 
// Apply a linear transform m to the ellipse
// m is an array representing a matrix :
// - -
// | m[0] m[2] |
// | m[1] m[3] |
// - -
//
Ellipse.prototype.transform = function (m) {
// We consider the current ellipse as image of the unit circle
// by first scale(rx,ry) and then rotate(ax) ...
// So we apply ma = m x rotate(ax) x scale(rx,ry) to the unit circle.
var c = Math.cos(this.ax * torad), s = Math.sin(this.ax * torad);
var ma = [
this.rx * (m[0]*c + m[2]*s),
this.rx * (m[1]*c + m[3]*s),
this.ry * (-m[0]*s + m[2]*c),
this.ry * (-m[1]*s + m[3]*c)
];
 
// ma * transpose(ma) = [ J L ]
// [ L K ]
// L is calculated later (if the image is not a circle)
var J = ma[0]*ma[0] + ma[2]*ma[2],
K = ma[1]*ma[1] + ma[3]*ma[3];
 
// the discriminant of the characteristic polynomial of ma * transpose(ma)
var D = ((ma[0]-ma[3])*(ma[0]-ma[3]) + (ma[2]+ma[1])*(ma[2]+ma[1])) *
((ma[0]+ma[3])*(ma[0]+ma[3]) + (ma[2]-ma[1])*(ma[2]-ma[1]));
 
// the "mean eigenvalue"
var JK = (J + K) / 2;
 
// check if the image is (almost) a circle
if (D < epsilon * JK) {
// if it is
this.rx = this.ry = Math.sqrt(JK);
this.ax = 0;
return this;
}
 
// if it is not a circle
var L = ma[0]*ma[1] + ma[2]*ma[3];
 
D = Math.sqrt(D);
 
// {l1,l2} = the two eigen values of ma * transpose(ma)
var l1 = JK + D/2,
l2 = JK - D/2;
// the x - axis - rotation angle is the argument of the l1 - eigenvector
this.ax = (Math.abs(L) < epsilon && Math.abs(l1 - K) < epsilon) ?
90
:
Math.atan(Math.abs(L) > Math.abs(l1 - K) ?
(l1 - J) / L
:
L / (l1 - K)
) * 180 / Math.PI;
 
// if ax > 0 => rx = sqrt(l1), ry = sqrt(l2), else exchange axes and ax += 90
if (this.ax >= 0) {
// if ax in [0,90]
this.rx = Math.sqrt(l1);
this.ry = Math.sqrt(l2);
} else {
// if ax in ]-90,0[ => exchange axes
this.ax += 90;
this.rx = Math.sqrt(l2);
this.ry = Math.sqrt(l1);
}
 
return this;
};
 
// Check if the ellipse is (almost) degenerate, i.e. rx = 0 or ry = 0
//
Ellipse.prototype.isDegenerate = function () {
return (this.rx < epsilon * this.ry || this.ry < epsilon * this.rx);
};
 
module.exports = Ellipse;
 
},{}],4:[function(require,module,exports){
'use strict';
 
// combine 2 matrixes
// m1, m2 - [a, b, c, d, e, g]
//
function combine(m1, m2) {
return [
m1[0] * m2[0] + m1[2] * m2[1],
m1[1] * m2[0] + m1[3] * m2[1],
m1[0] * m2[2] + m1[2] * m2[3],
m1[1] * m2[2] + m1[3] * m2[3],
m1[0] * m2[4] + m1[2] * m2[5] + m1[4],
m1[1] * m2[4] + m1[3] * m2[5] + m1[5]
];
}
 
 
function Matrix() {
if (!(this instanceof Matrix)) { return new Matrix(); }
this.queue = []; // list of matrixes to apply
this.cache = null; // combined matrix cache
}
 
 
Matrix.prototype.matrix = function (m) {
if (m[0] === 1 && m[1] === 0 && m[2] === 0 && m[3] === 1 && m[4] === 0 && m[5] === 0) {
return this;
}
this.cache = null;
this.queue.push(m);
return this;
};
 
 
Matrix.prototype.translate = function (tx, ty) {
if (tx !== 0 || ty !== 0) {
this.cache = null;
this.queue.push([ 1, 0, 0, 1, tx, ty ]);
}
return this;
};
 
 
Matrix.prototype.scale = function (sx, sy) {
if (sx !== 1 || sy !== 1) {
this.cache = null;
this.queue.push([ sx, 0, 0, sy, 0, 0 ]);
}
return this;
};
 
 
Matrix.prototype.rotate = function (angle, rx, ry) {
var rad, cos, sin;
 
if (angle !== 0) {
this.translate(rx, ry);
 
rad = angle * Math.PI / 180;
cos = Math.cos(rad);
sin = Math.sin(rad);
 
this.queue.push([ cos, sin, -sin, cos, 0, 0 ]);
this.cache = null;
 
this.translate(-rx, -ry);
}
return this;
};
 
 
Matrix.prototype.skewX = function (angle) {
if (angle !== 0) {
this.cache = null;
this.queue.push([ 1, 0, Math.tan(angle * Math.PI / 180), 1, 0, 0 ]);
}
return this;
};
 
 
Matrix.prototype.skewY = function (angle) {
if (angle !== 0) {
this.cache = null;
this.queue.push([ 1, Math.tan(angle * Math.PI / 180), 0, 1, 0, 0 ]);
}
return this;
};
 
 
// Flatten queue
//
Matrix.prototype.toArray = function () {
if (this.cache) {
return this.cache;
}
 
if (!this.queue.length) {
this.cache = [ 1, 0, 0, 1, 0, 0 ];
return this.cache;
}
 
this.cache = this.queue[0];
 
if (this.queue.length === 1) {
return this.cache;
}
 
for (var i = 1; i < this.queue.length; i++) {
this.cache = combine(this.cache, this.queue[i]);
}
 
return this.cache;
};
 
 
// Apply list of matrixes to (x,y) point.
// If `isRelative` set, `translate` component of matrix will be skipped
//
Matrix.prototype.calc = function (x, y, isRelative) {
var m;
 
// Don't change point on empty transforms queue
if (!this.queue.length) { return [ x, y ]; }
 
// Calculate final matrix, if not exists
//
// NB. if you deside to apply transforms to point one-by-one,
// they should be taken in reverse order
 
if (!this.cache) {
this.cache = this.toArray();
}
 
m = this.cache;
 
// Apply matrix to point
return [
x * m[0] + y * m[2] + (isRelative ? 0 : m[4]),
x * m[1] + y * m[3] + (isRelative ? 0 : m[5])
];
};
 
 
module.exports = Matrix;
 
},{}],5:[function(require,module,exports){
'use strict';
 
 
var paramCounts = { a: 7, c: 6, h: 1, l: 2, m: 2, r: 4, q: 4, s: 4, t: 2, v: 1, z: 0 };
 
var SPECIAL_SPACES = [
0x1680, 0x180E, 0x2000, 0x2001, 0x2002, 0x2003, 0x2004, 0x2005, 0x2006,
0x2007, 0x2008, 0x2009, 0x200A, 0x202F, 0x205F, 0x3000, 0xFEFF
];
 
function isSpace(ch) {
return (ch === 0x0A) || (ch === 0x0D) || (ch === 0x2028) || (ch === 0x2029) || // Line terminators
// White spaces
(ch === 0x20) || (ch === 0x09) || (ch === 0x0B) || (ch === 0x0C) || (ch === 0xA0) ||
(ch >= 0x1680 && SPECIAL_SPACES.indexOf(ch) >= 0);
}
 
function isCommand(code) {
/*eslint-disable no-bitwise*/
switch (code | 0x20) {
case 0x6D/* m */:
case 0x7A/* z */:
case 0x6C/* l */:
case 0x68/* h */:
case 0x76/* v */:
case 0x63/* c */:
case 0x73/* s */:
case 0x71/* q */:
case 0x74/* t */:
case 0x61/* a */:
case 0x72/* r */:
return true;
}
return false;
}
 
function isDigit(code) {
return (code >= 48 && code <= 57); // 0..9
}
 
function isDigitStart(code) {
return (code >= 48 && code <= 57) || /* 0..9 */
code === 0x2B || /* + */
code === 0x2D || /* - */
code === 0x2E; /* . */
}
 
 
function State(path) {
this.index = 0;
this.path = path;
this.max = path.length;
this.result = [];
this.param = 0.0;
this.err = '';
this.segmentStart = 0;
this.data = [];
}
 
function skipSpaces(state) {
while (state.index < state.max && isSpace(state.path.charCodeAt(state.index))) {
state.index++;
}
}
 
 
function scanParam(state) {
var start = state.index,
index = start,
max = state.max,
zeroFirst = false,
hasCeiling = false,
hasDecimal = false,
hasDot = false,
ch;
 
if (index >= max) {
state.err = 'SvgPath: missed param (at pos ' + index + ')';
return;
}
ch = state.path.charCodeAt(index);
 
if (ch === 0x2B/* + */ || ch === 0x2D/* - */) {
index++;
ch = (index < max) ? state.path.charCodeAt(index) : 0;
}
 
// This logic is shamelessly borrowed from Esprima
// https://github.com/ariya/esprimas
//
if (!isDigit(ch) && ch !== 0x2E/* . */) {
state.err = 'SvgPath: param should start with 0..9 or `.` (at pos ' + index + ')';
return;
}
 
if (ch !== 0x2E/* . */) {
zeroFirst = (ch === 0x30/* 0 */);
index++;
 
ch = (index < max) ? state.path.charCodeAt(index) : 0;
 
if (zeroFirst && index < max) {
// decimal number starts with '0' such as '09' is illegal.
if (ch && isDigit(ch)) {
state.err = 'SvgPath: numbers started with `0` such as `09` are ilegal (at pos ' + start + ')';
return;
}
}
 
while (index < max && isDigit(state.path.charCodeAt(index))) {
index++;
hasCeiling = true;
}
ch = (index < max) ? state.path.charCodeAt(index) : 0;
}
 
if (ch === 0x2E/* . */) {
hasDot = true;
index++;
while (isDigit(state.path.charCodeAt(index))) {
index++;
hasDecimal = true;
}
ch = (index < max) ? state.path.charCodeAt(index) : 0;
}
 
if (ch === 0x65/* e */ || ch === 0x45/* E */) {
if (hasDot && !hasCeiling && !hasDecimal) {
state.err = 'SvgPath: invalid float exponent (at pos ' + index + ')';
return;
}
 
index++;
 
ch = (index < max) ? state.path.charCodeAt(index) : 0;
if (ch === 0x2B/* + */ || ch === 0x2D/* - */) {
index++;
}
if (index < max && isDigit(state.path.charCodeAt(index))) {
while (index < max && isDigit(state.path.charCodeAt(index))) {
index++;
}
} else {
state.err = 'SvgPath: invalid float exponent (at pos ' + index + ')';
return;
}
}
 
state.index = index;
state.param = parseFloat(state.path.slice(start, index)) + 0.0;
}
 
 
function finalizeSegment(state) {
var cmd, cmdLC;
 
// Process duplicated commands (without comand name)
 
// This logic is shamelessly borrowed from Raphael
// https://github.com/DmitryBaranovskiy/raphael/
//
cmd = state.path[state.segmentStart];
cmdLC = cmd.toLowerCase();
 
var params = state.data;
 
if (cmdLC === 'm' && params.length > 2) {
state.result.push([ cmd, params[0], params[1] ]);
params = params.slice(2);
cmdLC = 'l';
cmd = (cmd === 'm') ? 'l' : 'L';
}
 
if (cmdLC === 'r') {
state.result.push([ cmd ].concat(params));
} else {
 
while (params.length >= paramCounts[cmdLC]) {
state.result.push([ cmd ].concat(params.splice(0, paramCounts[cmdLC])));
if (!paramCounts[cmdLC]) {
break;
}
}
}
}
 
 
function scanSegment(state) {
var max = state.max,
cmdCode, comma_found, need_params, i;
 
state.segmentStart = state.index;
cmdCode = state.path.charCodeAt(state.index);
 
if (!isCommand(cmdCode)) {
state.err = 'SvgPath: bad command ' + state.path[state.index] + ' (at pos ' + state.index + ')';
return;
}
 
need_params = paramCounts[state.path[state.index].toLowerCase()];
 
state.index++;
skipSpaces(state);
 
state.data = [];
 
if (!need_params) {
// Z
finalizeSegment(state);
return;
}
 
comma_found = false;
 
for (;;) {
for (i = need_params; i > 0; i--) {
scanParam(state);
if (state.err.length) {
return;
}
state.data.push(state.param);
 
skipSpaces(state);
comma_found = false;
 
if (state.index < max && state.path.charCodeAt(state.index) === 0x2C/* , */) {
state.index++;
skipSpaces(state);
comma_found = true;
}
}
 
// after ',' param is mandatory
if (comma_found) {
continue;
}
 
if (state.index >= state.max) {
break;
}
 
// Stop on next segment
if (!isDigitStart(state.path.charCodeAt(state.index))) {
break;
}
}
 
finalizeSegment(state);
}
 
 
/* Returns array of segments:
*
* [
* [ command, coord1, coord2, ... ]
* ]
*/
module.exports = function pathParse(svgPath) {
var state = new State(svgPath);
var max = state.max;
 
skipSpaces(state);
 
while (state.index < max && !state.err.length) {
scanSegment(state);
}
 
if (state.err.length) {
state.result = [];
 
} else if (state.result.length) {
 
if ('mM'.indexOf(state.result[0][0]) < 0) {
state.err = 'SvgPath: string should start with `M` or `m`';
state.result = [];
} else {
state.result[0][0] = 'M';
}
}
 
return {
err: state.err,
segments: state.result
};
};
 
},{}],6:[function(require,module,exports){
// SVG Path transformations library
//
// Usage:
//
// SvgPath('...')
// .translate(-150, -100)
// .scale(0.5)
// .translate(-150, -100)
// .toFixed(1)
// .toString()
//
 
'use strict';
 
 
var pathParse = require('./path_parse');
var transformParse = require('./transform_parse');
var matrix = require('./matrix');
var a2c = require('./a2c');
var ellipse = require('./ellipse');
 
 
// Class constructor
//
function SvgPath(path) {
if (!(this instanceof SvgPath)) { return new SvgPath(path); }
 
var pstate = pathParse(path);
 
// Array of path segments.
// Each segment is array [command, param1, param2, ...]
this.segments = pstate.segments;
 
// Error message on parse error.
this.err = pstate.err;
 
// Transforms stack for lazy evaluation
this.__stack = [];
}
 
 
SvgPath.prototype.__matrix = function (m) {
var self = this, i;
 
// Quick leave for empty matrix
if (!m.queue.length) { return; }
 
this.iterate(function (s, index, x, y) {
var p, result, name, isRelative;
 
switch (s[0]) {
 
// Process 'assymetric' commands separately
case 'v':
p = m.calc(0, s[1], true);
result = (p[0] === 0) ? [ 'v', p[1] ] : [ 'l', p[0], p[1] ];
break;
 
case 'V':
p = m.calc(x, s[1], false);
result = (p[0] === m.calc(x, y, false)[0]) ? [ 'V', p[1] ] : [ 'L', p[0], p[1] ];
break;
 
case 'h':
p = m.calc(s[1], 0, true);
result = (p[1] === 0) ? [ 'h', p[0] ] : [ 'l', p[0], p[1] ];
break;
 
case 'H':
p = m.calc(s[1], y, false);
result = (p[1] === m.calc(x, y, false)[1]) ? [ 'H', p[0] ] : [ 'L', p[0], p[1] ];
break;
 
case 'a':
case 'A':
// ARC is: ['A', rx, ry, x-axis-rotation, large-arc-flag, sweep-flag, x, y]
 
// Drop segment if arc is empty (end point === start point)
/*if ((s[0] === 'A' && s[6] === x && s[7] === y) ||
(s[0] === 'a' && s[6] === 0 && s[7] === 0)) {
return [];
}*/
 
// Transform rx, ry and the x-axis-rotation
var ma = m.toArray();
var e = ellipse(s[1], s[2], s[3]).transform(ma);
 
// flip sweep-flag if matrix is not orientation-preserving
if (ma[0] * ma[3] - ma[1] * ma[2] < 0) {
s[5] = s[5] ? '0' : '1';
}
 
// Transform end point as usual (without translation for relative notation)
p = m.calc(s[6], s[7], s[0] === 'a');
 
// Empty arcs can be ignored by renderer, but should not be dropped
// to avoid collisions with `S A S` and so on. Replace with empty line.
if ((s[0] === 'A' && s[6] === x && s[7] === y) ||
(s[0] === 'a' && s[6] === 0 && s[7] === 0)) {
result = [ s[0] === 'a' ? 'l' : 'L', p[0], p[1] ];
break;
}
 
// if the resulting ellipse is (almost) a segment ...
if (e.isDegenerate()) {
// replace the arc by a line
result = [ s[0] === 'a' ? 'l' : 'L', p[0], p[1] ];
} else {
// if it is a real ellipse
// s[0], s[4] and s[5] are not modified
result = [ s[0], e.rx, e.ry, e.ax, s[4], s[5], p[0], p[1] ];
}
 
break;
 
case 'm':
// Edge case. The very first `m` should be processed as absolute, if happens.
// Make sense for coord shift transforms.
isRelative = index > 0;
 
p = m.calc(s[1], s[2], isRelative);
result = [ 'm', p[0], p[1] ];
break;
 
default:
name = s[0];
result = [ name ];
isRelative = (name.toLowerCase() === name);
 
// Apply transformations to the segment
for (i = 1; i < s.length; i += 2) {
p = m.calc(s[i], s[i + 1], isRelative);
result.push(p[0], p[1]);
}
}
 
self.segments[index] = result;
}, true);
};
 
 
// Apply stacked commands
//
SvgPath.prototype.__evaluateStack = function () {
var m, i;
 
if (!this.__stack.length) { return; }
 
if (this.__stack.length === 1) {
this.__matrix(this.__stack[0]);
this.__stack = [];
return;
}
 
m = matrix();
i = this.__stack.length;
 
while (--i >= 0) {
m.matrix(this.__stack[i].toArray());
}
 
this.__matrix(m);
this.__stack = [];
};
 
 
// Convert processed SVG Path back to string
//
SvgPath.prototype.toString = function () {
var elements = [], skipCmd, cmd;
 
this.__evaluateStack();
 
for (var i = 0; i < this.segments.length; i++) {
// remove repeating commands names
cmd = this.segments[i][0];
skipCmd = i > 0 && cmd !== 'm' && cmd !== 'M' && cmd === this.segments[i - 1][0];
elements = elements.concat(skipCmd ? this.segments[i].slice(1) : this.segments[i]);
}
 
return elements.join(' ')
// Optimizations: remove spaces around commands & before `-`
//
// We could also remove leading zeros for `0.5`-like values,
// but their count is too small to spend time for.
.replace(/ ?([achlmqrstvz]) ?/gi, '$1')
.replace(/ \-/g, '-')
// workaround for FontForge SVG importing bug
.replace(/zm/g, 'z m');
};
 
 
// Translate path to (x [, y])
//
SvgPath.prototype.translate = function (x, y) {
this.__stack.push(matrix().translate(x, y || 0));
return this;
};
 
 
// Scale path to (sx [, sy])
// sy = sx if not defined
//
SvgPath.prototype.scale = function (sx, sy) {
this.__stack.push(matrix().scale(sx, (!sy && (sy !== 0)) ? sx : sy));
return this;
};
 
 
// Rotate path around point (sx [, sy])
// sy = sx if not defined
//
SvgPath.prototype.rotate = function (angle, rx, ry) {
this.__stack.push(matrix().rotate(angle, rx || 0, ry || 0));
return this;
};
 
 
// Skew path along the X axis by `degrees` angle
//
SvgPath.prototype.skewX = function (degrees) {
this.__stack.push(matrix().skewX(degrees));
return this;
};
 
 
// Skew path along the Y axis by `degrees` angle
//
SvgPath.prototype.skewY = function (degrees) {
this.__stack.push(matrix().skewY(degrees));
return this;
};
 
 
// Apply matrix transform (array of 6 elements)
//
SvgPath.prototype.matrix = function (m) {
this.__stack.push(matrix().matrix(m));
return this;
};
 
 
// Transform path according to "transform" attr of SVG spec
//
SvgPath.prototype.transform = function (transformString) {
if (!transformString.trim()) {
return this;
}
this.__stack.push(transformParse(transformString));
return this;
};
 
 
// Round coords with given decimal precition.
// 0 by default (to integers)
//
SvgPath.prototype.round = function (d) {
var contourStartDeltaX = 0, contourStartDeltaY = 0, deltaX = 0, deltaY = 0, l;
 
d = d || 0;
 
this.__evaluateStack();
 
this.segments.forEach(function (s) {
var isRelative = (s[0].toLowerCase() === s[0]);
 
switch (s[0]) {
case 'H':
case 'h':
if (isRelative) { s[1] += deltaX; }
deltaX = s[1] - s[1].toFixed(d);
s[1] = +s[1].toFixed(d);
return;
 
case 'V':
case 'v':
if (isRelative) { s[1] += deltaY; }
deltaY = s[1] - s[1].toFixed(d);
s[1] = +s[1].toFixed(d);
return;
 
case 'Z':
case 'z':
deltaX = contourStartDeltaX;
deltaY = contourStartDeltaY;
return;
 
case 'M':
case 'm':
if (isRelative) {
s[1] += deltaX;
s[2] += deltaY;
}
 
deltaX = s[1] - s[1].toFixed(d);
deltaY = s[2] - s[2].toFixed(d);
 
contourStartDeltaX = deltaX;
contourStartDeltaY = deltaY;
 
s[1] = +s[1].toFixed(d);
s[2] = +s[2].toFixed(d);
return;
 
case 'A':
case 'a':
// [cmd, rx, ry, x-axis-rotation, large-arc-flag, sweep-flag, x, y]
if (isRelative) {
s[6] += deltaX;
s[7] += deltaY;
}
 
deltaX = s[6] - s[6].toFixed(d);
deltaY = s[7] - s[7].toFixed(d);
 
s[1] = +s[1].toFixed(d);
s[2] = +s[2].toFixed(d);
s[3] = +s[3].toFixed(d + 2); // better precision for rotation
s[6] = +s[6].toFixed(d);
s[7] = +s[7].toFixed(d);
return;
 
default:
// a c l q s t
l = s.length;
 
if (isRelative) {
s[l - 2] += deltaX;
s[l - 1] += deltaY;
}
 
deltaX = s[l - 2] - s[l - 2].toFixed(d);
deltaY = s[l - 1] - s[l - 1].toFixed(d);
 
s.forEach(function (val, i) {
if (!i) { return; }
s[i] = +s[i].toFixed(d);
});
return;
}
});
 
return this;
};
 
 
// Apply iterator function to all segments. If function returns result,
// current segment will be replaced to array of returned segments.
// If empty array is returned, current regment will be deleted.
//
SvgPath.prototype.iterate = function (iterator, keepLazyStack) {
var segments = this.segments,
replacements = {},
needReplace = false,
lastX = 0,
lastY = 0,
countourStartX = 0,
countourStartY = 0;
var i, j, newSegments;
 
if (!keepLazyStack) {
this.__evaluateStack();
}
 
segments.forEach(function (s, index) {
 
var res = iterator(s, index, lastX, lastY);
 
if (Array.isArray(res)) {
replacements[index] = res;
needReplace = true;
}
 
var isRelative = (s[0] === s[0].toLowerCase());
 
// calculate absolute X and Y
switch (s[0]) {
case 'm':
case 'M':
lastX = s[1] + (isRelative ? lastX : 0);
lastY = s[2] + (isRelative ? lastY : 0);
countourStartX = lastX;
countourStartY = lastY;
return;
 
case 'h':
case 'H':
lastX = s[1] + (isRelative ? lastX : 0);
return;
 
case 'v':
case 'V':
lastY = s[1] + (isRelative ? lastY : 0);
return;
 
case 'z':
case 'Z':
// That make sence for multiple contours
lastX = countourStartX;
lastY = countourStartY;
return;
 
default:
lastX = s[s.length - 2] + (isRelative ? lastX : 0);
lastY = s[s.length - 1] + (isRelative ? lastY : 0);
}
});
 
// Replace segments if iterator return results
 
if (!needReplace) { return this; }
 
newSegments = [];
 
for (i = 0; i < segments.length; i++) {
if (typeof replacements[i] !== 'undefined') {
for (j = 0; j < replacements[i].length; j++) {
newSegments.push(replacements[i][j]);
}
} else {
newSegments.push(segments[i]);
}
}
 
this.segments = newSegments;
 
return this;
};
 
 
// Converts segments from relative to absolute
//
SvgPath.prototype.abs = function () {
 
this.iterate(function (s, index, x, y) {
var name = s[0],
nameUC = name.toUpperCase(),
i;
 
// Skip absolute commands
if (name === nameUC) { return; }
 
s[0] = nameUC;
 
switch (name) {
case 'v':
// v has shifted coords parity
s[1] += y;
return;
 
case 'a':
// ARC is: ['A', rx, ry, x-axis-rotation, large-arc-flag, sweep-flag, x, y]
// touch x, y only
s[6] += x;
s[7] += y;
return;
 
default:
for (i = 1; i < s.length; i++) {
s[i] += i % 2 ? x : y; // odd values are X, even - Y
}
}
}, true);
 
return this;
};
 
 
// Converts segments from absolute to relative
//
SvgPath.prototype.rel = function () {
 
this.iterate(function (s, index, x, y) {
var name = s[0],
nameLC = name.toLowerCase(),
i;
 
// Skip relative commands
if (name === nameLC) { return; }
 
// Don't touch the first M to avoid potential confusions.
if (index === 0 && name === 'M') { return; }
 
s[0] = nameLC;
 
switch (name) {
case 'V':
// V has shifted coords parity
s[1] -= y;
return;
 
case 'A':
// ARC is: ['A', rx, ry, x-axis-rotation, large-arc-flag, sweep-flag, x, y]
// touch x, y only
s[6] -= x;
s[7] -= y;
return;
 
default:
for (i = 1; i < s.length; i++) {
s[i] -= i % 2 ? x : y; // odd values are X, even - Y
}
}
}, true);
 
return this;
};
 
 
// Converts arcs to cubic bézier curves
//
SvgPath.prototype.unarc = function () {
this.iterate(function (s, index, x, y) {
var new_segments, nextX, nextY, result = [], name = s[0];
 
// Skip anything except arcs
if (name !== 'A' && name !== 'a') { return null; }
 
if (name === 'a') {
// convert relative arc coordinates to absolute
nextX = x + s[6];
nextY = y + s[7];
} else {
nextX = s[6];
nextY = s[7];
}
 
new_segments = a2c(x, y, nextX, nextY, s[4], s[5], s[1], s[2], s[3]);
 
// Degenerated arcs can be ignored by renderer, but should not be dropped
// to avoid collisions with `S A S` and so on. Replace with empty line.
if (new_segments.length === 0) {
return [ [ s[0] === 'a' ? 'l' : 'L', s[6], s[7] ] ];
}
 
new_segments.forEach(function (s) {
result.push([ 'C', s[2], s[3], s[4], s[5], s[6], s[7] ]);
});
 
return result;
});
 
return this;
};
 
 
// Converts smooth curves (with missed control point) to generic curves
//
SvgPath.prototype.unshort = function () {
var segments = this.segments;
var prevControlX, prevControlY, prevSegment;
var curControlX, curControlY;
 
// TODO: add lazy evaluation flag when relative commands supported
 
this.iterate(function (s, idx, x, y) {
var name = s[0], nameUC = name.toUpperCase(), isRelative;
 
// First command MUST be M|m, it's safe to skip.
// Protect from access to [-1] for sure.
if (!idx) { return; }
 
if (nameUC === 'T') { // quadratic curve
isRelative = (name === 't');
 
prevSegment = segments[idx - 1];
 
if (prevSegment[0] === 'Q') {
prevControlX = prevSegment[1] - x;
prevControlY = prevSegment[2] - y;
} else if (prevSegment[0] === 'q') {
prevControlX = prevSegment[1] - prevSegment[3];
prevControlY = prevSegment[2] - prevSegment[4];
} else {
prevControlX = 0;
prevControlY = 0;
}
 
curControlX = -prevControlX;
curControlY = -prevControlY;
 
if (!isRelative) {
curControlX += x;
curControlY += y;
}
 
segments[idx] = [
isRelative ? 'q' : 'Q',
curControlX, curControlY,
s[1], s[2]
];
 
} else if (nameUC === 'S') { // cubic curve
isRelative = (name === 's');
 
prevSegment = segments[idx - 1];
 
if (prevSegment[0] === 'C') {
prevControlX = prevSegment[3] - x;
prevControlY = prevSegment[4] - y;
} else if (prevSegment[0] === 'c') {
prevControlX = prevSegment[3] - prevSegment[5];
prevControlY = prevSegment[4] - prevSegment[6];
} else {
prevControlX = 0;
prevControlY = 0;
}
 
curControlX = -prevControlX;
curControlY = -prevControlY;
 
if (!isRelative) {
curControlX += x;
curControlY += y;
}
 
segments[idx] = [
isRelative ? 'c' : 'C',
curControlX, curControlY,
s[1], s[2], s[3], s[4]
];
}
});
 
return this;
};
 
 
module.exports = SvgPath;
 
},{"./a2c":2,"./ellipse":3,"./matrix":4,"./path_parse":5,"./transform_parse":7}],7:[function(require,module,exports){
'use strict';
 
 
var Matrix = require('./matrix');
 
var operations = {
matrix: true,
scale: true,
rotate: true,
translate: true,
skewX: true,
skewY: true
};
 
var CMD_SPLIT_RE = /\s*(matrix|translate|scale|rotate|skewX|skewY)\s*\(\s*(.+?)\s*\)[\s,]*/;
var PARAMS_SPLIT_RE = /[\s,]+/;
 
 
module.exports = function transformParse(transformString) {
var matrix = new Matrix();
var cmd, params;
 
// Split value into ['', 'translate', '10 50', '', 'scale', '2', '', 'rotate', '-45', '']
transformString.split(CMD_SPLIT_RE).forEach(function (item) {
 
// Skip empty elements
if (!item.length) { return; }
 
// remember operation
if (typeof operations[item] !== 'undefined') {
cmd = item;
return;
}
 
// extract params & att operation to matrix
params = item.split(PARAMS_SPLIT_RE).map(function (i) {
return +i || 0;
});
 
// If params count is not correct - ignore command
switch (cmd) {
case 'matrix':
if (params.length === 6) {
matrix.matrix(params);
}
return;
 
case 'scale':
if (params.length === 1) {
matrix.scale(params[0], params[0]);
} else if (params.length === 2) {
matrix.scale(params[0], params[1]);
}
return;
 
case 'rotate':
if (params.length === 1) {
matrix.rotate(params[0], 0, 0);
} else if (params.length === 3) {
matrix.rotate(params[0], params[1], params[2]);
}
return;
 
case 'translate':
if (params.length === 1) {
matrix.translate(params[0], 0);
} else if (params.length === 2) {
matrix.translate(params[0], params[1]);
}
return;
 
case 'skewX':
if (params.length === 1) {
matrix.skewX(params[0]);
}
return;
 
case 'skewY':
if (params.length === 1) {
matrix.skewY(params[0]);
}
return;
}
});
 
return matrix;
};
 
},{"./matrix":4}],8:[function(require,module,exports){
/**
* A class to parse color values
* @author Stoyan Stefanov <sstoo@gmail.com>
* @link http://www.phpied.com/rgb-color-parser-in-javascript/
* @license Use it if you like it
*/
(function (global) {
function RGBColor(color_string)
{
this.ok = false;
 
// strip any leading #
if (color_string.charAt(0) == '#') { // remove # if any
color_string = color_string.substr(1,6);
}
 
color_string = color_string.replace(/ /g,'');
color_string = color_string.toLowerCase();
 
// before getting into regexps, try simple matches
// and overwrite the input
var simple_colors = {
aliceblue: 'f0f8ff',
antiquewhite: 'faebd7',
aqua: '00ffff',
aquamarine: '7fffd4',
azure: 'f0ffff',
beige: 'f5f5dc',
bisque: 'ffe4c4',
black: '000000',
blanchedalmond: 'ffebcd',
blue: '0000ff',
blueviolet: '8a2be2',
brown: 'a52a2a',
burlywood: 'deb887',
cadetblue: '5f9ea0',
chartreuse: '7fff00',
chocolate: 'd2691e',
coral: 'ff7f50',
cornflowerblue: '6495ed',
cornsilk: 'fff8dc',
crimson: 'dc143c',
cyan: '00ffff',
darkblue: '00008b',
darkcyan: '008b8b',
darkgoldenrod: 'b8860b',
darkgray: 'a9a9a9',
darkgreen: '006400',
darkkhaki: 'bdb76b',
darkmagenta: '8b008b',
darkolivegreen: '556b2f',
darkorange: 'ff8c00',
darkorchid: '9932cc',
darkred: '8b0000',
darksalmon: 'e9967a',
darkseagreen: '8fbc8f',
darkslateblue: '483d8b',
darkslategray: '2f4f4f',
darkturquoise: '00ced1',
darkviolet: '9400d3',
deeppink: 'ff1493',
deepskyblue: '00bfff',
dimgray: '696969',
dodgerblue: '1e90ff',
feldspar: 'd19275',
firebrick: 'b22222',
floralwhite: 'fffaf0',
forestgreen: '228b22',
fuchsia: 'ff00ff',
gainsboro: 'dcdcdc',
ghostwhite: 'f8f8ff',
gold: 'ffd700',
goldenrod: 'daa520',
gray: '808080',
green: '008000',
greenyellow: 'adff2f',
honeydew: 'f0fff0',
hotpink: 'ff69b4',
indianred : 'cd5c5c',
indigo : '4b0082',
ivory: 'fffff0',
khaki: 'f0e68c',
lavender: 'e6e6fa',
lavenderblush: 'fff0f5',
lawngreen: '7cfc00',
lemonchiffon: 'fffacd',
lightblue: 'add8e6',
lightcoral: 'f08080',
lightcyan: 'e0ffff',
lightgoldenrodyellow: 'fafad2',
lightgrey: 'd3d3d3',
lightgreen: '90ee90',
lightpink: 'ffb6c1',
lightsalmon: 'ffa07a',
lightseagreen: '20b2aa',
lightskyblue: '87cefa',
lightslateblue: '8470ff',
lightslategray: '778899',
lightsteelblue: 'b0c4de',
lightyellow: 'ffffe0',
lime: '00ff00',
limegreen: '32cd32',
linen: 'faf0e6',
magenta: 'ff00ff',
maroon: '800000',
mediumaquamarine: '66cdaa',
mediumblue: '0000cd',
mediumorchid: 'ba55d3',
mediumpurple: '9370d8',
mediumseagreen: '3cb371',
mediumslateblue: '7b68ee',
mediumspringgreen: '00fa9a',
mediumturquoise: '48d1cc',
mediumvioletred: 'c71585',
midnightblue: '191970',
mintcream: 'f5fffa',
mistyrose: 'ffe4e1',
moccasin: 'ffe4b5',
navajowhite: 'ffdead',
navy: '000080',
oldlace: 'fdf5e6',
olive: '808000',
olivedrab: '6b8e23',
orange: 'ffa500',
orangered: 'ff4500',
orchid: 'da70d6',
palegoldenrod: 'eee8aa',
palegreen: '98fb98',
paleturquoise: 'afeeee',
palevioletred: 'd87093',
papayawhip: 'ffefd5',
peachpuff: 'ffdab9',
peru: 'cd853f',
pink: 'ffc0cb',
plum: 'dda0dd',
powderblue: 'b0e0e6',
purple: '800080',
red: 'ff0000',
rosybrown: 'bc8f8f',
royalblue: '4169e1',
saddlebrown: '8b4513',
salmon: 'fa8072',
sandybrown: 'f4a460',
seagreen: '2e8b57',
seashell: 'fff5ee',
sienna: 'a0522d',
silver: 'c0c0c0',
skyblue: '87ceeb',
slateblue: '6a5acd',
slategray: '708090',
snow: 'fffafa',
springgreen: '00ff7f',
steelblue: '4682b4',
tan: 'd2b48c',
teal: '008080',
thistle: 'd8bfd8',
tomato: 'ff6347',
turquoise: '40e0d0',
violet: 'ee82ee',
violetred: 'd02090',
wheat: 'f5deb3',
white: 'ffffff',
whitesmoke: 'f5f5f5',
yellow: 'ffff00',
yellowgreen: '9acd32'
};
for (var key in simple_colors) {
if (color_string == key) {
color_string = simple_colors[key];
}
}
// emd of simple type-in colors
 
// array of color definition objects
var color_defs = [
{
re: /^rgb\((\d{1,3}),\s*(\d{1,3}),\s*(\d{1,3})\)$/,
example: ['rgb(123, 234, 45)', 'rgb(255,234,245)'],
process: function (bits){
return [
parseInt(bits[1]),
parseInt(bits[2]),
parseInt(bits[3])
];
}
},
{
re: /^(\w{2})(\w{2})(\w{2})$/,
example: ['#00ff00', '336699'],
process: function (bits){
return [
parseInt(bits[1], 16),
parseInt(bits[2], 16),
parseInt(bits[3], 16)
];
}
},
{
re: /^(\w{1})(\w{1})(\w{1})$/,
example: ['#fb0', 'f0f'],
process: function (bits){
return [
parseInt(bits[1] + bits[1], 16),
parseInt(bits[2] + bits[2], 16),
parseInt(bits[3] + bits[3], 16)
];
}
}
];
 
// search through the definitions to find a match
for (var i = 0; i < color_defs.length; i++) {
var re = color_defs[i].re;
var processor = color_defs[i].process;
var bits = re.exec(color_string);
if (bits) {
var channels = processor(bits);
this.r = channels[0];
this.g = channels[1];
this.b = channels[2];
this.ok = true;
}
 
}
 
// validate/cleanup values
this.r = (this.r < 0 || isNaN(this.r)) ? 0 : ((this.r > 255) ? 255 : this.r);
this.g = (this.g < 0 || isNaN(this.g)) ? 0 : ((this.g > 255) ? 255 : this.g);
this.b = (this.b < 0 || isNaN(this.b)) ? 0 : ((this.b > 255) ? 255 : this.b);
 
// some getters
this.toRGB = function () {
return 'rgb(' + this.r + ', ' + this.g + ', ' + this.b + ')';
}
this.toHex = function () {
var r = this.r.toString(16);
var g = this.g.toString(16);
var b = this.b.toString(16);
if (r.length == 1) r = '0' + r;
if (g.length == 1) g = '0' + g;
if (b.length == 1) b = '0' + b;
return '#' + r + g + b;
}
 
// help
this.getHelpXML = function () {
 
var examples = new Array();
// add regexps
for (var i = 0; i < color_defs.length; i++) {
var example = color_defs[i].example;
for (var j = 0; j < example.length; j++) {
examples[examples.length] = example[j];
}
}
// add type-in colors
for (var sc in simple_colors) {
examples[examples.length] = sc;
}
 
var xml = document.createElement('ul');
xml.setAttribute('id', 'rgbcolor-examples');
for (var i = 0; i < examples.length; i++) {
try {
var list_item = document.createElement('li');
var list_color = new RGBColor(examples[i]);
var example_div = document.createElement('div');
example_div.style.cssText =
'margin: 3px; '
+ 'border: 1px solid black; '
+ 'background:' + list_color.toHex() + '; '
+ 'color:' + list_color.toHex()
;
example_div.appendChild(document.createTextNode('test'));
var list_item_value = document.createTextNode(
' ' + examples[i] + ' -> ' + list_color.toRGB() + ' -> ' + list_color.toHex()
);
list_item.appendChild(example_div);
list_item.appendChild(list_item_value);
xml.appendChild(list_item);
 
} catch(e){}
}
return xml;
 
}
 
}
if (typeof define === "function" && define.amd) {
define(function () {
return RGBColor;
});
} else if (typeof module !== "undefined" && module.exports) {
module.exports = RGBColor;
} else {
global.RGBColor = RGBColor;
}
return RGBColor;
})(typeof self !== "undefined" && self || typeof window !== "undefined" && window || this);
 
},{}],9:[function(require,module,exports){
/*
The MIT License (MIT)
 
Copyright (c) 2015-2016 yWorks GmbH
 
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
 
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
 
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
 
/**
* Renders an svg element to a jsPDF document.
* For accurate results a DOM document is required (mainly used for text size measurement and image format conversion)
* @param element {HTMLElement} The svg element, which will be cloned, so the original stays unchanged.
* @param pdf {jsPDF} The jsPDF object.
* @param options {object} An object that may contain render options. Currently supported are:
* scale: The global factor by which everything is scaled.
* xOffset, yOffset: Offsets that are added to every coordinate AFTER scaling (They are not
* influenced by the scale attribute).
*/
(function (global) {
var RGBColor;
var SvgPath;
 
var _pdf; // jsPDF pdf-document
 
var cToQ = 2 / 3; // ratio to convert quadratic bezier curves to cubic ones
 
var iriReference = /url\(#([^)]+)\)/;
 
 
// pathSegList is marked deprecated in chrome, so parse the d attribute manually if necessary
var getPathSegList = function (node) {
var d = node.getAttribute("d");
 
// Replace arcs before path segment list is handled
if (SvgPath) {
d = SvgPath(d).unshort().unarc().abs().toString();
node.setAttribute('d', d);
}
 
var pathSegList = node.pathSegList;
if (pathSegList) {
return pathSegList;
}
 
pathSegList = [];
 
var regex = /([a-df-zA-DF-Z])([^a-df-zA-DF-Z]*)/g,
match;
while (match = regex.exec(d)) {
var coords = parseFloats(match[2]);
 
var type = match[1];
var length = "zZ".indexOf(type) >= 0 ? 0 :
"hHvV".indexOf(type) >= 0 ? 1 :
"mMlLtT".indexOf(type) >= 0 ? 2 :
"sSqQ".indexOf(type) >= 0 ? 4 :
"aA".indexOf(type) >= 0 ? 7 :
"cC".indexOf(type) >= 0 ? 6 : -1;
 
var i = 0;
do {
var pathSeg = {pathSegTypeAsLetter: type};
switch (type) {
case "h":
case "H":
pathSeg.x = coords[i];
break;
 
case "v":
case "V":
pathSeg.y = coords[i];
break;
 
case "c":
case "C":
pathSeg.x1 = coords[i + length - 6];
pathSeg.y1 = coords[i + length - 5];
case "s":
case "S":
pathSeg.x2 = coords[i + length - 4];
pathSeg.y2 = coords[i + length - 3];
case "t":
case "T":
case "l":
case "L":
case "m":
case "M":
pathSeg.x = coords[i + length - 2];
pathSeg.y = coords[i + length - 1];
break;
 
case "q":
case "Q":
pathSeg.x1 = coords[i];
pathSeg.y1 = coords[i + 1];
pathSeg.x = coords[i + 2];
pathSeg.y = coords[i + 3];
break;
case "a":
case "A":
throw new Error("Cannot convert Arcs without SvgPath package");
}
 
pathSegList.push(pathSeg);
i += length;
} while(i < coords.length);
}
 
pathSegList.getItem = function (i) {
return this[i]
};
pathSegList.numberOfItems = pathSegList.length;
 
return pathSegList;
};
 
// returns an attribute of a node, either from the node directly or from css
var getAttribute = function (node, propertyNode, propertyCss) {
propertyCss = propertyCss || propertyNode;
return node.getAttribute(propertyNode) || node.style[propertyCss];
};
 
var nodeIs = function (node, tagsString) {
return tagsString.split(",").indexOf(node.tagName.toLowerCase()) >= 0;
};
 
var forEachChild = function (node, fn) {
// copy list of children, as the original might be modified
var children = [];
for (var i = 0; i < node.childNodes.length; i++) {
var childNode = node.childNodes[i];
if (childNode.nodeName.charAt(0) !== "#")
children.push(childNode);
}
for (i = 0; i < children.length; i++) {
fn(i, children[i]);
}
};
 
var getAngle = function (from, to) {
return Math.atan2(to[1] - from[1], to[0] - from[0]);
};
 
// mirrors p1 at p2
var mirrorPoint = function (p1, p2) {
var dx = p2[0] - p1[0];
var dy = p2[1] - p1[1];
 
return [p1[0] + 2 * dx, p1[1] + 2 * dy];
};
 
// transforms a cubic bezier control point to a quadratic one: returns from + (2/3) * (to - from)
var toCubic = function (from, to) {
return [cToQ * (to[0] - from[0]) + from[0], cToQ * (to[1] - from[1]) + from[1]];
};
 
// extracts a control point from a previous path segment (for t,T,s,S segments)
var getControlPointFromPrevious = function (i, from, list, prevX, prevY) {
var prev = list.getItem(i - 1);
var p2;
if (i > 0 && (prev.pathSegTypeAsLetter === "C" || prev.pathSegTypeAsLetter === "S")) {
p2 = mirrorPoint([prev.x2, prev.y2], from);
} else if (i > 0 && (prev.pathSegTypeAsLetter === "c" || prev.pathSegTypeAsLetter === "s")) {
p2 = mirrorPoint([prev.x2 + prevX, prev.y2 + prevY], from);
} else {
p2 = [from[0], from[1]];
}
return p2;
};
 
// an id prefix to handle duplicate ids
var SvgPrefix = function (prefix) {
this.prefix = prefix;
this.id = 0;
this.nextChild = function () {
return new SvgPrefix("_" + this.id++ + "_" + this.get());
};
this.get = function () {
return this.prefix;
}
};
 
// returns the node for the specified id or incrementally removes prefixes to search "higher" levels
var getFromDefs = function (id, defs) {
var regExp = /_\d+_/;
while (!defs[id] && regExp.exec(id)) {
id = id.replace(regExp, "");
}
return defs[id];
};
 
// replace any newline characters by space and trim
var removeNewlinesAndTrim = function (str) {
return str.replace(/[\n\s\r]+/, " ").trim();
};
 
// clones the defs object (or basically any object)
var cloneDefs = function (defs) {
var clone = {};
for (var key in defs) {
if (defs.hasOwnProperty(key)) {
clone[key] = defs[key];
}
}
return clone;
};
 
// computes the transform directly applied at the node (such as viewbox scaling and the "transform" atrribute)
// x,y,cx,cy,r,... are omitted
var computeNodeTransform = function (node) {
var height, width, viewBoxHeight, viewBoxWidth, bounds, viewBox, y, x;
var nodeTransform = _pdf.unitMatrix;
if (nodeIs(node, "svg,g")) {
x = parseFloat(node.getAttribute("x")) || 0;
y = parseFloat(node.getAttribute("y")) || 0;
 
// jquery doesn't like camelCase notation...
viewBox = node.getAttribute("viewBox");
if (viewBox) {
bounds = parseFloats(viewBox);
viewBoxWidth = bounds[2] - bounds[0];
viewBoxHeight = bounds[3] - bounds[1];
width = parseFloat(node.getAttribute("width")) || viewBoxWidth;
height = parseFloat(node.getAttribute("height")) || viewBoxHeight;
nodeTransform = new _pdf.Matrix(width / viewBoxWidth, 0, 0, height / viewBoxHeight, x - bounds[0], y - bounds[1]);
} else {
nodeTransform = new _pdf.Matrix(1, 0, 0, 1, x, y);
}
} else if (nodeIs(node, "marker")) {
x = -parseFloat(node.getAttribute("refX")) || 0;
y = -parseFloat(node.getAttribute("refY")) || 0;
 
viewBox = node.getAttribute("viewBox");
if (viewBox) {
bounds = parseFloats(viewBox);
viewBoxWidth = bounds[2] - bounds[0];
viewBoxHeight = bounds[3] - bounds[1];
width = parseFloat(node.getAttribute("markerWidth")) || viewBoxWidth;
height = parseFloat(node.getAttribute("markerHeight")) || viewBoxHeight;
 
var s = new _pdf.Matrix(width / viewBoxWidth, 0, 0, height / viewBoxHeight, 0, 0);
var t = new _pdf.Matrix(1, 0, 0, 1, x, y);
nodeTransform = _pdf.matrixMult(t, s);
} else {
nodeTransform = new _pdf.Matrix(1, 0, 0, 1, x, y);
}
}
 
var transformString = node.getAttribute("transform");
if (!transformString)
return nodeTransform;
else
return _pdf.matrixMult(nodeTransform, parseTransform(transformString));
};
 
// parses the "points" string used by polygons and returns an array of points
var parsePointsString = function (string) {
var floats = parseFloats(string);
var result = [];
for (var i = 0; i < floats.length - 1; i += 2) {
var x = floats[i];
var y = floats[i + 1];
result.push([x, y]);
}
return result;
};
 
// parses the "transform" string
var parseTransform = function (transformString) {
if (!transformString)
return _pdf.unitMatrix;
 
var mRegex = /^\s*matrix\(([^\)]+)\)\s*/,
tRegex = /^\s*translate\(([^\)]+)\)\s*/,
rRegex = /^\s*rotate\(([^\)]+)\)\s*/,
sRegex = /^\s*scale\(([^\)]+)\)\s*/,
sXRegex = /^\s*skewX\(([^\)]+)\)\s*/,
sYRegex = /^\s*skewY\(([^\)]+)\)\s*/;
 
var resultMatrix = _pdf.unitMatrix, m;
 
while (transformString.length > 0) {
var match = mRegex.exec(transformString);
if (match) {
m = parseFloats(match[1]);
resultMatrix = _pdf.matrixMult(new _pdf.Matrix(m[0], m[1], m[2], m[3], m[4], m[5]), resultMatrix);
transformString = transformString.substr(match[0].length);
}
match = rRegex.exec(transformString);
if (match) {
m = parseFloats(match[1]);
var a = Math.PI * m[0] / 180;
resultMatrix = _pdf.matrixMult(new _pdf.Matrix(Math.cos(a), Math.sin(a), -Math.sin(a), Math.cos(a), 0, 0), resultMatrix);
if (m[1] && m[2]) {
var t1 = new _pdf.Matrix(1, 0, 0, 1, m[1], m[2]);
var t2 = new _pdf.Matrix(1, 0, 0, 1, -m[1], -m[2]);
resultMatrix = _pdf.matrixMult(t2, _pdf.matrixMult(resultMatrix, t1));
}
transformString = transformString.substr(match[0].length);
}
match = tRegex.exec(transformString);
if (match) {
m = parseFloats(match[1]);
resultMatrix = _pdf.matrixMult(new _pdf.Matrix(1, 0, 0, 1, m[0], m[1] || 0), resultMatrix);
transformString = transformString.substr(match[0].length);
}
match = sRegex.exec(transformString);
if (match) {
m = parseFloats(match[1]);
if (!m[1])
m[1] = m[0];
resultMatrix = _pdf.matrixMult(new _pdf.Matrix(m[0], 0, 0, m[1], 0, 0), resultMatrix);
transformString = transformString.substr(match[0].length);
}
match = sXRegex.exec(transformString);
if (match) {
m = parseFloat(match[1]);
resultMatrix = _pdf.matrixMult(new _pdf.Matrix(1, 0, Math.tan(m), 1, 0, 0), resultMatrix);
transformString = transformString.substr(match[0].length);
}
match = sYRegex.exec(transformString);
if (match) {
m = parseFloat(match[1]);
resultMatrix = _pdf.matrixMult(new _pdf.Matrix(1, Math.tan(m), 0, 1, 0, 0), resultMatrix);
transformString = transformString.substr(match[0].length);
}
}
return resultMatrix;
};
 
// parses a comma, sign and/or whitespace separated string of floats and returns the single floats in an array
var parseFloats = function (str) {
var floats = [], match,
regex = /[+-]?(?:(?:\d+\.?\d*)|(?:\d*\.?\d+))(?:[eE][+-]?\d+)?/g;
while(match = regex.exec(str)) {
floats.push(parseFloat(match[0]));
}
return floats;
};
 
// extends RGBColor by rgba colors as RGBColor is not capable of it
var parseColor = function (colorString) {
var match = /\s*rgba\(((?:[^,\)]*,){3}[^,\)]*)\)\s*/.exec(colorString);
if (match) {
var floats = parseFloats(match[1]);
var color = new RGBColor("rgb(" + floats.slice(0,3).join(",") + ")");
color.a = floats[3];
return color;
} else {
return new RGBColor(colorString);
}
};
 
// multiplies a vector with a matrix: vec' = vec * matrix
var multVecMatrix = function (vec, matrix) {
var x = vec[0];
var y = vec[1];
return [
matrix.a * x + matrix.c * y + matrix.e,
matrix.b * x + matrix.d * y + matrix.f
];
};
 
// returns the untransformed bounding box [x, y, width, height] of an svg element (quite expensive for path and polygon objects, as
// the whole points/d-string has to be processed)
var getUntransformedBBox = function (node) {
var i, minX, minY, maxX, maxY, viewBox, vb, boundingBox;
var pf = parseFloat;
 
if (nodeIs(node, "polygon")) {
var points = parsePointsString(node.getAttribute("points"));
minX = Number.POSITIVE_INFINITY;
minY = Number.POSITIVE_INFINITY;
maxX = Number.NEGATIVE_INFINITY;
maxY = Number.NEGATIVE_INFINITY;
for (i = 0; i < points.length; i++) {
var point = points[i];
minX = Math.min(minX, point[0]);
maxX = Math.max(maxX, point[0]);
minY = Math.min(minY, point[1]);
maxY = Math.max(maxY, point[1]);
}
boundingBox = [
minX,
minY,
maxX - minX,
maxY - minY
];
} else if (nodeIs(node, "path")) {
var list = getPathSegList(node);
minX = Number.POSITIVE_INFINITY;
minY = Number.POSITIVE_INFINITY;
maxX = Number.NEGATIVE_INFINITY;
maxY = Number.NEGATIVE_INFINITY;
var x = 0, y = 0;
var prevX, prevY, newX, newY;
var p2, p3, to;
for (i = 0; i < list.numberOfItems; i++) {
var seg = list.getItem(i);
var cmd = seg.pathSegTypeAsLetter;
switch (cmd) {
case "H":
newX = seg.x;
newY = y;
break;
case "h":
newX = seg.x + x;
newY = y;
break;
case "V":
newX = x;
newY = seg.y;
break;
case "v":
newX = x;
newY = seg.y + y;
break;
case "C":
p2 = [seg.x1, seg.y1];
p3 = [seg.x2, seg.y2];
to = [seg.x, seg.y];
break;
case "c":
p2 = [seg.x1 + x, seg.y1 + y];
p3 = [seg.x2 + x, seg.y2 + y];
to = [seg.x + x, seg.y + y];
break;
case "S":
p2 = getControlPointFromPrevious(i, [x, y], list, prevX, prevY);
p3 = [seg.x2, seg.y2];
to = [seg.x, seg.y];
break;
case "s":
p2 = getControlPointFromPrevious(i, [x, y], list, prevX, prevY);
p3 = [seg.x2 + x, seg.y2 + y];
to = [seg.x + x, seg.y + y];
break;
case "Q":
pf = [seg.x1, seg.y1];
p2 = toCubic([x, y], pf);
p3 = toCubic([seg.x, seg.y], pf);
to = [seg.x, seg.y];
break;
case "q":
pf = [seg.x1 + x, seg.y1 + y];
p2 = toCubic([x, y], pf);
p3 = toCubic([x + seg.x, y + seg.y], pf);
to = [seg.x + x, seg.y + y];
break;
case "T":
p2 = getControlPointFromPrevious(i, [x, y], list, prevX, prevY);
p2 = toCubic([x, y], pf);
p3 = toCubic([seg.x, seg.y], pf);
to = [seg.x, seg.y];
break;
case "t":
pf = getControlPointFromPrevious(i, [x, y], list, prevX, prevY);
p2 = toCubic([x, y], pf);
p3 = toCubic([x + seg.x, y + seg.y], pf);
to = [seg.x + x, seg.y + y];
break;
// TODO: A,a
}
if ("sScCqQtT".indexOf(cmd) >= 0) {
prevX = x;
prevY = y;
}
if ("MLCSQT".indexOf(cmd) >= 0) {
x = seg.x;
y = seg.y;
} else if ("mlcsqt".indexOf(cmd) >= 0) {
x = seg.x + x;
y = seg.y + y;
} else if ("zZ".indexOf(cmd) < 0) {
x = newX;
y = newY;
}
if ("CSQTcsqt".indexOf(cmd) >= 0) {
minX = Math.min(minX, x, p2[0], p3[0], to[0]);
maxX = Math.max(maxX, x, p2[0], p3[0], to[0]);
minY = Math.min(minY, y, p2[1], p3[1], to[1]);
maxY = Math.max(maxY, y, p2[1], p3[1], to[1]);
} else {
minX = Math.min(minX, x);
maxX = Math.max(maxX, x);
minY = Math.min(minY, y);
maxY = Math.max(maxY, y);
}
}
boundingBox = [
minX,
minY,
maxX - minX,
maxY - minY
];
} else if (nodeIs(node, "svg")) {
viewBox = node.getAttribute("viewBox");
if (viewBox) {
vb = parseFloats(viewBox);
}
return [
pf(node.getAttribute("x")) || (vb && vb[0]) || 0,
pf(node.getAttribute("y")) || (vb && vb[1]) || 0,
pf(node.getAttribute("width")) || (vb && vb[2]) || 0,
pf(node.getAttribute("height")) || (vb && vb[3]) || 0
];
} else if (nodeIs(node, "g")) {
boundingBox = [0, 0, 0, 0];
forEachChild(node, function (i, node) {
var nodeBox = getUntransformedBBox(node);
boundingBox = [
Math.min(boundingBox[0], nodeBox[0]),
Math.min(boundingBox[1], nodeBox[1]),
Math.max(boundingBox[0] + boundingBox[2], nodeBox[0] + nodeBox[2]) - Math.min(boundingBox[0], nodeBox[0]),
Math.max(boundingBox[1] + boundingBox[3], nodeBox[1] + nodeBox[3]) - Math.min(boundingBox[1], nodeBox[1])
];
});
} else if (nodeIs(node, "marker")) {
viewBox = node.getAttribute("viewBox");
if (viewBox) {
vb = parseFloats(viewBox);
}
return [
(vb && vb[0]) || 0,
(vb && vb[1]) || 0,
(vb && vb[2]) || pf(node.getAttribute("marker-width")) || 0,
(vb && vb[3]) || pf(node.getAttribute("marker-height")) || 0
];
} else if (nodeIs(node, "pattern")) {
return [
pf(node.getAttribute("x")) || 0,
pf(node.getAttribute("y")) || 0,
pf(node.getAttribute("width")) || 0,
pf(node.getAttribute("height")) || 0
]
} else {
// TODO: check if there are other possible coordinate attributes
var x1 = pf(node.getAttribute("x1")) || pf(node.getAttribute("x")) || pf((node.getAttribute("cx")) - pf(node.getAttribute("r"))) || 0;
var x2 = pf(node.getAttribute("x2")) || (x1 + pf(node.getAttribute("width"))) || (pf(node.getAttribute("cx")) + pf(node.getAttribute("r"))) || 0;
var y1 = pf(node.getAttribute("y1")) || pf(node.getAttribute("y")) || (pf(node.getAttribute("cy")) - pf(node.getAttribute("r"))) || 0;
var y2 = pf(node.getAttribute("y2")) || (y1 + pf(node.getAttribute("height"))) || (pf(node.getAttribute("cy")) + pf(node.getAttribute("r"))) || 0;
boundingBox = [
Math.min(x1, x2),
Math.min(y1, y2),
Math.max(x1, x2) - Math.min(x1, x2),
Math.max(y1, y2) - Math.min(y1, y2)
];
}
 
if (!nodeIs(node, "marker,svg,g")) {
// add line-width
var lineWidth = getAttribute(node, "stroke-width") || 1;
var miterLimit = getAttribute(node, "stroke-miterlimit");
// miterLength / lineWidth = 1 / sin(phi / 2)
miterLimit && (lineWidth *= 0.5 / (Math.sin(Math.PI / 12)));
return [
boundingBox[0] - lineWidth,
boundingBox[1] - lineWidth,
boundingBox[2] + 2 * lineWidth,
boundingBox[3] + 2 * lineWidth
];
}
 
return boundingBox;
};
 
// transforms a bounding box and returns a new rect that contains it
var transformBBox = function (box, matrix) {
var bl = multVecMatrix([box[0], box[1]], matrix);
var br = multVecMatrix([box[0] + box[2], box[1]], matrix);
var tl = multVecMatrix([box[0], box[1] + box[3]], matrix);
var tr = multVecMatrix([box[0] + box[2], box[1] + box[3]], matrix);
 
var bottom = Math.min(bl[1], br[1], tl[1], tr[1]);
var left = Math.min(bl[0], br[0], tl[0], tr[0]);
var top = Math.max(bl[1], br[1], tl[1], tr[1]);
var right = Math.max(bl[0], br[0], tl[0], tr[0]);
 
return [
left,
bottom,
right - left,
top - bottom
]
};
 
// draws a polygon
var polygon = function (node, tfMatrix, colorMode, gradient, gradientMatrix) {
var points = parsePointsString(node.getAttribute("points"));
var lines = [{op: "m", c: multVecMatrix(points[0], tfMatrix)}];
for (var i = 1; i < points.length; i++) {
var p = points[i];
var to = multVecMatrix(p, tfMatrix);
lines.push({op: "l", c: to});
}
lines.push({op: "h"});
_pdf.path(lines, colorMode, gradient, gradientMatrix);
};
 
// draws an image (converts it to jpeg first, as jsPDF doesn't support png or other formats)
var image = function (node) {
// convert image to jpeg
var imageUrl = node.getAttribute("xlink:href") || node.getAttribute("href");
var image = new Image();
image.src = imageUrl;
 
var canvas = document.createElement("canvas");
var width = parseFloat(node.getAttribute("width")),
height = parseFloat(node.getAttribute("height")),
x = parseFloat(node.getAttribute("x") || 0),
y = parseFloat(node.getAttribute("y") || 0);
canvas.width = width;
canvas.height = height;
var context = canvas.getContext("2d");
context.fillStyle = "#fff";
context.fillRect(0, 0, width, height);
context.drawImage(image, 0, 0, width, height);
var jpegUrl = canvas.toDataURL("image/jpeg");
 
_pdf.addImage(jpegUrl,
"jpeg",
x,
y,
width,
height
);
};
 
// draws a path
var path = function (node, tfMatrix, svgIdPrefix, colorMode, gradient, gradientMatrix) {
var list = getPathSegList(node);
var markerEnd = node.getAttribute("marker-end"),
markerStart = node.getAttribute("marker-start"),
markerMid = node.getAttribute("marker-mid");
 
var getLinesFromPath = function (pathSegList, tfMatrix) {
var x = 0, y = 0;
var x0 = x, y0 = y;
var prevX, prevY, newX, newY;
var to, p, p2, p3;
var lines = [];
var markers = [];
var op;
var prevAngle = 0, curAngle;
 
var addMarker = function (angle, anchor, type) {
var cos = Math.cos(angle);
var sin = Math.sin(angle);
var tf;
tf = new _pdf.Matrix(cos, sin, -sin, cos, anchor[0], anchor[1]);
markers.push({type: type, tf: _pdf.matrixMult(tf, tfMatrix)});
};
 
for (var i = 0; i < list.numberOfItems; i++) {
var seg = list.getItem(i);
var cmd = seg.pathSegTypeAsLetter;
switch (cmd) {
case "M":
x0 = x;
y0 = y;
to = [seg.x, seg.y];
op = "m";
break;
case "m":
x0 = x;
y0 = y;
to = [seg.x + x, seg.y + y];
op = "m";
break;
case "L":
to = [seg.x, seg.y];
op = "l";
break;
case "l":
to = [seg.x + x, seg.y + y];
op = "l";
break;
case "H":
to = [seg.x, y];
op = "l";
newX = seg.x;
newY = y;
break;
case "h":
to = [seg.x + x, y];
op = "l";
newX = seg.x + x;
newY = y;
break;
case "V":
to = [x, seg.y];
op = "l";
newX = x;
newY = seg.y;
break;
case "v":
to = [x, seg.y + y];
op = "l";
newX = x;
newY = seg.y + y;
break;
case "C":
p2 = [seg.x1, seg.y1];
p3 = [seg.x2, seg.y2];
to = [seg.x, seg.y];
break;
case "c":
p2 = [seg.x1 + x, seg.y1 + y];
p3 = [seg.x2 + x, seg.y2 + y];
to = [seg.x + x, seg.y + y];
break;
case "S":
p2 = getControlPointFromPrevious(i, [x, y], list, prevX, prevY);
p3 = [seg.x2, seg.y2];
to = [seg.x, seg.y];
break;
case "s":
p2 = getControlPointFromPrevious(i, [x, y], list, prevX, prevY);
p3 = [seg.x2 + x, seg.y2 + y];
to = [seg.x + x, seg.y + y];
break;
case "Q":
p = [seg.x1, seg.y1];
p2 = toCubic([x, y], p);
p3 = toCubic([seg.x, seg.y], p);
to = [seg.x, seg.y];
break;
case "q":
p = [seg.x1 + x, seg.y1 + y];
p2 = toCubic([x, y], p);
p3 = toCubic([x + seg.x, y + seg.y], p);
to = [seg.x + x, seg.y + y];
break;
case "T":
p2 = getControlPointFromPrevious(i, [x, y], list, prevX, prevY);
p2 = toCubic([x, y], p);
p3 = toCubic([seg.x, seg.y], p);
to = [seg.x, seg.y];
break;
case "t":
p = getControlPointFromPrevious(i, [x, y], list, prevX, prevY);
p2 = toCubic([x, y], p);
p3 = toCubic([x + seg.x, y + seg.y], p);
to = [seg.x + x, seg.y + y];
break;
// TODO: A,a
case "Z":
case "z":
x = x0;
y = y0;
lines.push({op: "h"});
break;
}
 
var hasStartMarker = markerStart
&& (i === 1
|| ("mM".indexOf(cmd) < 0 && "mM".indexOf(list.getItem(i - 1).pathSegTypeAsLetter) >= 0));
var hasEndMarker = markerEnd
&& (i === list.numberOfItems - 1
|| ("mM".indexOf(cmd) < 0 && "mM".indexOf(list.getItem(i + 1).pathSegTypeAsLetter) >= 0));
var hasMidMarker = markerMid
&& i > 0
&& !(i === 1 && "mM".indexOf(list.getItem(i - 1).pathSegTypeAsLetter) >= 0);
 
if ("sScCqQtT".indexOf(cmd) >= 0) {
hasStartMarker && addMarker(getAngle([x, y], p2), [x, y], "start");
hasEndMarker && addMarker(getAngle(p3, to), to, "end");
if (hasMidMarker) {
curAngle = getAngle([x, y], p2);
curAngle = "mM".indexOf(list.getItem(i - 1).pathSegTypeAsLetter) >= 0 ?
curAngle : .5 * (prevAngle + curAngle);
addMarker(curAngle, [x, y], "mid");
}
 
prevAngle = getAngle(p3, to);
 
prevX = x;
prevY = y;
p2 = multVecMatrix(p2, tfMatrix);
p3 = multVecMatrix(p3, tfMatrix);
p = multVecMatrix(to, tfMatrix);
lines.push({
op: "c", c: [
p2[0], p2[1],
p3[0], p3[1],
p[0], p[1]
]
});
} else if ("lLhHvVmM".indexOf(cmd) >= 0) {
curAngle = getAngle([x, y], to);
hasStartMarker && addMarker(curAngle, [x, y], "start");
hasEndMarker && addMarker(curAngle, to, "end");
if (hasMidMarker) {
var angle = "mM".indexOf(cmd) >= 0 ?
prevAngle : "mM".indexOf(list.getItem(i - 1).pathSegTypeAsLetter) >= 0 ?
curAngle : .5 * (prevAngle + curAngle);
addMarker(angle, [x, y], "mid");
}
prevAngle = curAngle;
 
p = multVecMatrix(to, tfMatrix);
lines.push({op: op, c: p});
}
 
if ("MLCSQT".indexOf(cmd) >= 0) {
x = seg.x;
y = seg.y;
} else if ("mlcsqt".indexOf(cmd) >= 0) {
x = seg.x + x;
y = seg.y + y;
} else if ("zZ".indexOf(cmd) < 0) {
x = newX;
y = newY;
}
}
 
return {lines: lines, markers: markers};
};
var lines = getLinesFromPath(list, tfMatrix);
 
if (markerEnd || markerStart || markerMid) {
for (var i = 0; i < lines.markers.length; i++) {
var marker = lines.markers[i];
var markerElement;
switch (marker.type) {
case "start":
markerElement = svgIdPrefix.get() + iriReference.exec(markerStart)[1];
break;
case "end":
markerElement = svgIdPrefix.get() + iriReference.exec(markerEnd)[1];
break;
case "mid":
markerElement = svgIdPrefix.get() + iriReference.exec(markerMid)[1];
break;
}
_pdf.doFormObject(markerElement, marker.tf);
}
}
 
if (lines.lines.length > 0) {
_pdf.path(lines.lines, colorMode, gradient, gradientMatrix);
}
};
 
// draws the element referenced by a use node, makes use of pdf's XObjects/FormObjects so nodes are only written once
// to the pdf document. This highly reduces the file size and computation time.
var use = function (node, tfMatrix, svgIdPrefix) {
var url = (node.getAttribute("href") || node.getAttribute("xlink:href"));
// just in case someone has the idea to use empty use-tags, wtf???
if (!url)
return;
 
// get the size of the referenced form object (to apply the correct scaling)
var formObject = _pdf.getFormObject(svgIdPrefix.get() + url.substring(1));
 
// scale and position it right
var x = node.getAttribute("x") || 0;
var y = node.getAttribute("y") || 0;
var width = node.getAttribute("width") || formObject.width;
var height = node.getAttribute("height") || formObject.height;
var t = new _pdf.Matrix(width / formObject.width || 0, 0, 0, height / formObject.height || 0, x, y);
t = _pdf.matrixMult(t, tfMatrix);
_pdf.doFormObject(svgIdPrefix.get() + url.substring(1), t);
};
 
// draws a line
var line = function (node, tfMatrix) {
var p1 = multVecMatrix([parseFloat(node.getAttribute('x1')), parseFloat(node.getAttribute('y1'))], tfMatrix);
var p2 = multVecMatrix([parseFloat(node.getAttribute('x2')), parseFloat(node.getAttribute('y2'))], tfMatrix);
_pdf.line(p1[0], p1[1], p2[0], p2[1]);
};
 
// draws a rect
var rect = function (node, colorMode, gradient, gradientMatrix) {
_pdf.roundedRect(
parseFloat(node.getAttribute('x')) || 0,
parseFloat(node.getAttribute('y')) || 0,
parseFloat(node.getAttribute('width')),
parseFloat(node.getAttribute('height')),
parseFloat(node.getAttribute('rx')) || 0,
parseFloat(node.getAttribute('ry')) || 0,
colorMode,
gradient,
gradientMatrix
);
};
 
// draws an ellipse
var ellipse = function (node, colorMode, gradient, gradientMatrix) {
_pdf.ellipse(
parseFloat(node.getAttribute('cx')) || 0,
parseFloat(node.getAttribute('cy')) || 0,
parseFloat(node.getAttribute('rx')),
parseFloat(node.getAttribute('ry')),
colorMode,
gradient,
gradientMatrix
);
};
 
// draws a circle
var circle = function (node, colorMode, gradient, gradientMatrix) {
var radius = parseFloat(node.getAttribute('r')) || 0;
_pdf.ellipse(
parseFloat(node.getAttribute('cx')) || 0,
parseFloat(node.getAttribute('cy')) || 0,
radius,
radius,
colorMode,
gradient,
gradientMatrix
);
};
 
// applies text transformations to a text node
var transformText = function (node, text) {
var textTransform = getAttribute(node, "text-transform");
switch (textTransform) {
case "uppercase": return text.toUpperCase();
case "lowercase": return text.toLowerCase();
default: return text;
// TODO: capitalize, full-width
}
};
 
// draws a text element and its tspan children
var text = function (node, tfMatrix, hasFillColor, fillRGB) {
_pdf.saveGraphicsState();
setTextProperties(node, fillRGB);
 
var getTextOffset = function (textAnchor, width) {
var xOffset = 0;
switch (textAnchor) {
case 'end':
xOffset = width;
break;
case 'middle':
xOffset = width / 2;
break;
case 'start':
break;
}
return xOffset;
};
 
/**
* Convert em, px and bare number attributes to pixel values
*/
var toPixels = function (value, pdfFontSize) {
var match;
 
// em
match = value && value.toString().match(/^([\-0-9.]+)em$/);
if (match) {
return parseFloat(match[1]) * pdfFontSize;
}
 
// pixels
match = value && value.toString().match(/^([\-0-9.]+)(px|)$/);
if (match) {
return parseFloat(match[1]);
}
return 0;
};
 
// creates an svg element and append the text node to properly measure the text size
var svg = document.createElementNS("http://www.w3.org/2000/svg", "svg");
svg.appendChild(node);
svg.setAttribute("visibility", "hidden");
document.body.appendChild(svg);
 
var box = node.getBBox();
var x, y, xOffset = 0;
var textAnchor = getAttribute(node, "text-anchor");
if (textAnchor) {
xOffset = getTextOffset(textAnchor, box.width);
}
 
var pdfFontSize = _pdf.getFontSize();
var textX = toPixels(node.getAttribute('x'), pdfFontSize);
var textY = toPixels(node.getAttribute('y'), pdfFontSize);
var m = _pdf.matrixMult(new _pdf.Matrix(1, 0, 0, 1, textX, textY), tfMatrix);
 
x = toPixels(node.getAttribute("dx"), pdfFontSize);
y = toPixels(node.getAttribute("dy"), pdfFontSize);
 
// when there are no tspans draw the text directly
if (node.childElementCount === 0) {
_pdf.text(
(x - xOffset),
y,
transformText(node, removeNewlinesAndTrim(node.textContent)),
void 0,
m
);
} else {
// otherwise loop over tspans and position each relative to the previous one
forEachChild(node, function (i, tSpan) {
if (!tSpan.textContent || nodeIs(tSpan, 'title,desc,metadata')) {
return;
}
_pdf.saveGraphicsState();
var tSpanColor = getAttribute(tSpan, "fill");
setTextProperties(tSpan, tSpanColor && new RGBColor(tSpanColor));
var extent = tSpan.getExtentOfChar(0);
_pdf.text(
extent.x - textX,//x - xOffset,
extent.y + extent.height * 0.7 - textY, // 0.7 roughly mimicks the text baseline
transformText(node, removeNewlinesAndTrim(tSpan.textContent)),
void 0,
m
);
 
_pdf.restoreGraphicsState();
});
 
}
 
document.body.removeChild(svg);
_pdf.restoreGraphicsState();
};
 
// As defs elements are allowed to appear after they are referenced, we search for them first
var findAndRenderDefs = function (node, tfMatrix, defs, svgIdPrefix, withinDefs) {
forEachChild(node, function (i, child) {
if (child.tagName.toLowerCase() === "defs") {
renderNode(child, tfMatrix, defs, svgIdPrefix, withinDefs);
// prevent defs from being evaluated twice // TODO: make this better
child.parentNode.removeChild(child);
}
});
};
 
// processes a svg node
var svg = function (node, tfMatrix, defs, svgIdPrefix, withinDefs) {
// create a new prefix and clone the defs, as defs within the svg should not be visible outside
var newSvgIdPrefix = svgIdPrefix.nextChild();
var newDefs = cloneDefs(defs);
findAndRenderDefs(node, tfMatrix, newDefs, newSvgIdPrefix, withinDefs);
renderChildren(node, tfMatrix, newDefs, newSvgIdPrefix, withinDefs);
};
 
// renders all children of a node
var renderChildren = function (node, tfMatrix, defs, svgIdPrefix, withinDefs) {
forEachChild(node, function (i, node) {
renderNode(node, tfMatrix, defs, svgIdPrefix, withinDefs);
});
};
 
// adds a gradient to defs and the pdf document for later use, type is either "axial" or "radial"
// opacity is only supported rudimentary by averaging over all stops
// transforms are applied on use
var putGradient = function (node, type, coords, defs, svgIdPrefix) {
var colors = [];
var opacitySum = 0;
var hasOpacity = false;
var gState;
forEachChild(node, function (i, element) {
// since opacity gradients are hard to realize, average the opacity over the control points
if (element.tagName.toLowerCase() === "stop") {
var color = new RGBColor(getAttribute(element, "stop-color"));
colors.push({
offset: parseFloat(element.getAttribute("offset")),
color: [color.r, color.g, color.b]
});
var opacity = getAttribute(element, "stop-opacity");
if (opacity && opacity != 1) {
opacitySum += parseFloat(opacity);
hasOpacity = true;
}
}
});
 
if (hasOpacity) {
gState = new _pdf.GState({opacity: opacitySum / coords.length});
}
 
var pattern = new _pdf.ShadingPattern(type, coords, colors, gState);
var id = svgIdPrefix.get() + node.getAttribute("id");
_pdf.addShadingPattern(id, pattern);
defs[id] = node;
};
 
var pattern = function (node, defs, svgIdPrefix) {
var id = svgIdPrefix.get() + node.getAttribute("id");
defs[id] = node;
 
// the transformations directly at the node are written to the pattern transformation matrix
var bBox = getUntransformedBBox(node);
var pattern = new _pdf.TilingPattern([bBox[0], bBox[1], bBox[0] + bBox[2], bBox[1] + bBox[3]], bBox[2], bBox[3],
null, computeNodeTransform(node));
 
_pdf.beginTilingPattern(pattern);
// continue without transformation
renderChildren(node, _pdf.unitMatrix, defs, svgIdPrefix, false);
_pdf.endTilingPattern(id, pattern);
};
 
function setTextProperties(node, fillRGB) {
var fontFamily = getAttribute(node, "font-family");
if (fontFamily) {
_pdf.setFont(fontFamily);
}
 
if (fillRGB && fillRGB.ok) {
_pdf.setTextColor(fillRGB.r, fillRGB.g, fillRGB.b);
}
 
var fontType;
var fontWeight = getAttribute(node, "font-weight");
if (fontWeight) {
if (fontWeight === "bold") {
fontType = "bold";
}
}
 
var fontStyle = getAttribute(node, "font-style");
if (fontStyle) {
if (fontStyle === "italic") {
fontType += "italic";
}
}
_pdf.setFontType(fontType);
 
var pdfFontSize = 16;
var fontSize = getAttribute(node, "font-size");
if (fontSize) {
pdfFontSize = parseFloat(fontSize);
_pdf.setFontSize(pdfFontSize);
}
}
 
 
/**
* Renders a svg node.
* @param node The svg element
* @param contextTransform The current transformation matrix
* @param defs The defs map holding all svg nodes that can be referenced
* @param svgIdPrefix The current id prefix
* @param withinDefs True iff we are top-level within a defs node, so the target can be switched to an pdf form object
*/
var renderNode = function (node, contextTransform, defs, svgIdPrefix, withinDefs) {
var tfMatrix,
hasFillColor = false,
fillRGB = null,
colorMode = null,
fillUrl = null,
fillData = null,
bBox;
 
//
// Decide about the render target and set the correct transformation
//
 
// if we are within a defs node, start a new pdf form object and draw this node and all children on that instead
// of the top-level page
var targetIsFormObject = withinDefs && !nodeIs(node, "lineargradient,radialgradient,pattern");
if (targetIsFormObject) {
 
// the transformations directly at the node are written to the pdf form object transformation matrix
tfMatrix = computeNodeTransform(node);
bBox = getUntransformedBBox(node);
 
_pdf.beginFormObject(bBox[0], bBox[1], bBox[2], bBox[3], tfMatrix);
 
// continue without transformation and set withinDefs to false to prevent child nodes from starting new form objects
tfMatrix = _pdf.unitMatrix;
withinDefs = false;
 
} else {
tfMatrix = _pdf.matrixMult(computeNodeTransform(node), contextTransform);
_pdf.saveGraphicsState();
}
 
//
// extract fill and stroke mode
//
 
// fill mode
if (nodeIs(node, "g,path,rect,text,ellipse,line,circle,polygon")) {
function setDefaultColor() {
fillRGB = new RGBColor("rgb(0, 0, 0)");
hasFillColor = true;
colorMode = "F";
}
 
var fillColor = getAttribute(node, "fill");
if (fillColor) {
var url = iriReference.exec(fillColor);
if (url) {
// probably a gradient (or something unsupported)
fillUrl = svgIdPrefix.get() + url[1];
var fill = getFromDefs(fillUrl, defs);
if (fill && nodeIs(fill, "lineargradient,radialgradient")) {
 
// matrix to convert between gradient space and user space
// for "userSpaceOnUse" this is the current transformation: tfMatrix
// for "objectBoundingBox" or default, the gradient gets scaled and transformed to the bounding box
var gradientUnitsMatrix = tfMatrix;
if (!fill.hasAttribute("gradientUnits")
|| fill.getAttribute("gradientUnits").toLowerCase() === "objectboundingbox") {
bBox || (bBox = getUntransformedBBox(node));
gradientUnitsMatrix = new _pdf.Matrix(bBox[2], 0, 0, bBox[3], bBox[0], bBox[1]);
 
var nodeTransform = computeNodeTransform(node);
gradientUnitsMatrix = _pdf.matrixMult(gradientUnitsMatrix, nodeTransform);
}
 
// matrix that is applied to the gradient before any other transformations
var gradientTransform = parseTransform(fill.getAttribute("gradientTransform"));
 
fillData = _pdf.matrixMult(gradientTransform, gradientUnitsMatrix);
} else if (fill && nodeIs(fill, "pattern")) {
var fillBBox, y, width, height, x;
fillData = {};
 
var patternUnitsMatrix = _pdf.unitMatrix;
if (!fill.hasAttribute("patternUnits")
|| fill.getAttribute("patternUnits").toLowerCase() === "objectboundingbox") {
bBox || (bBox = getUntransformedBBox(node));
patternUnitsMatrix = new _pdf.Matrix(1, 0, 0, 1, bBox[0], bBox[1]);
 
// TODO: slightly inaccurate (rounding errors? line width bBoxes?)
fillBBox = getUntransformedBBox(fill);
x = fillBBox[0] * bBox[0];
y = fillBBox[1] * bBox[1];
width = fillBBox[2] * bBox[2];
height = fillBBox[3] * bBox[3];
fillData.boundingBox = [x, y, x + width, y + height];
fillData.xStep = width;
fillData.yStep = height;
}
 
var patternContentUnitsMatrix = _pdf.unitMatrix;
if (fill.hasAttribute("patternContentUnits")
&& fill.getAttribute("patternContentUnits").toLowerCase() === "objectboundingbox") {
bBox || (bBox = getUntransformedBBox(node));
patternContentUnitsMatrix = new _pdf.Matrix(bBox[2], 0, 0, bBox[3], 0, 0);
 
fillBBox = fillData.boundingBox || getUntransformedBBox(fill);
x = fillBBox[0] / bBox[0];
y = fillBBox[1] / bBox[1];
width = fillBBox[2] / bBox[2];
height = fillBBox[3] / bBox[3];
fillData.boundingBox = [x, y, x + width, y + height];
fillData.xStep = width;
fillData.yStep = height;
}
 
fillData.matrix = _pdf.matrixMult(
_pdf.matrixMult(patternContentUnitsMatrix, patternUnitsMatrix), tfMatrix);
 
colorMode = "F";
} else {
// unsupported fill argument (e.g. patterns) -> fill black
fillUrl = fill = null;
setDefaultColor();
}
} else {
// plain color
fillRGB = parseColor(fillColor);
if (fillRGB.ok) {
hasFillColor = true;
colorMode = 'F';
} else {
colorMode = null;
}
}
} else {
// if no fill attribute is provided the default fill color is black
setDefaultColor();
}
 
// opacity is realized via a pdf graphics state
var opacity = 1.0;
var nodeOpacity = node.getAttribute("opacity") || node.getAttribute("fill-opacity");
if (nodeOpacity) {
opacity *= parseFloat(nodeOpacity);
}
if (fillRGB && typeof fillRGB.a === "number") {
opacity *= fillRGB.a;
}
_pdf.setGState(new _pdf.GState({opacity: opacity}));
}
 
if (nodeIs(node, "g,path,rect,ellipse,line,circle,polygon")) {
// text has no fill color, so don't apply it until here
if (hasFillColor) {
_pdf.setFillColor(fillRGB.r, fillRGB.g, fillRGB.b);
}
 
// stroke mode
var strokeColor = node.getAttribute('stroke');
if (strokeColor) {
var strokeWidth;
if (node.hasAttribute("stroke-width")) {
strokeWidth = Math.abs(parseFloat(node.getAttribute('stroke-width')));
_pdf.setLineWidth(strokeWidth);
}
var strokeRGB = new RGBColor(strokeColor);
if (strokeRGB.ok) {
_pdf.setDrawColor(strokeRGB.r, strokeRGB.g, strokeRGB.b);
if (strokeWidth !== 0) {
// pdf spec states: "A line width of 0 denotes the thinnest line that can be rendered at device resolution:
// 1 device pixel wide". SVG, however, does not draw zero width lines.
colorMode = (colorMode || "") + "D";
}
}
if (node.hasAttribute("stroke-linecap")) {
_pdf.setLineCap(node.getAttribute("stroke-linecap"));
}
if (node.hasAttribute("stroke-linejoin")) {
_pdf.setLineJoin(node.getAttribute("stroke-linejoin"));
}
if (node.hasAttribute("stroke-dasharray")) {
_pdf.setLineDashPattern(
parseFloats(node.getAttribute("stroke-dasharray")),
parseInt(node.getAttribute("stroke-dashoffset")) || 0
);
}
if (node.hasAttribute("stroke-miterlimit")) {
_pdf.setLineMiterLimit(parseFloat(node.getAttribute("stroke-miterlimit")));
}
}
}
 
setTextProperties(node, fillRGB);
 
// do the actual drawing
switch (node.tagName.toLowerCase()) {
case 'svg':
svg(node, tfMatrix, defs, svgIdPrefix, withinDefs);
break;
case 'g':
findAndRenderDefs(node, tfMatrix, defs, svgIdPrefix, withinDefs);
case 'a':
case "marker":
renderChildren(node, tfMatrix, defs, svgIdPrefix, withinDefs);
break;
 
case 'defs':
renderChildren(node, tfMatrix, defs, svgIdPrefix, true);
break;
 
case 'use':
use(node, tfMatrix, svgIdPrefix);
break;
 
case 'line':
line(node, tfMatrix);
break;
 
case 'rect':
_pdf.setCurrentTransformationMatrix(tfMatrix);
rect(node, colorMode, fillUrl, fillData);
break;
 
case 'ellipse':
_pdf.setCurrentTransformationMatrix(tfMatrix);
ellipse(node, colorMode, fillUrl, fillData);
break;
 
case 'circle':
_pdf.setCurrentTransformationMatrix(tfMatrix);
circle(node, colorMode, fillUrl, fillData);
break;
case 'text':
text(node, tfMatrix, hasFillColor, fillRGB);
break;
 
case 'path':
path(node, tfMatrix, svgIdPrefix, colorMode, fillUrl, fillData);
break;
 
case 'polygon':
polygon(node, tfMatrix, colorMode, fillUrl, fillData);
break;
 
case 'image':
_pdf.setCurrentTransformationMatrix(tfMatrix);
image(node);
break;
 
case "lineargradient":
putGradient(node, "axial", [
node.getAttribute("x1"),
node.getAttribute("y1"),
node.getAttribute("x2"),
node.getAttribute("y2")
], defs, svgIdPrefix);
break;
 
case "radialgradient":
putGradient(node, "radial", [
node.getAttribute("fx") || node.getAttribute("cx"),
node.getAttribute("fy") || node.getAttribute("cy"),
0,
node.getAttribute("cx") || 0,
node.getAttribute("cy") || 0,
node.getAttribute("r") || 0
], defs, svgIdPrefix);
break;
 
case "pattern":
pattern(node, defs, svgIdPrefix);
break;
}
 
// close either the formObject or the graphics context
if (targetIsFormObject) {
_pdf.endFormObject(svgIdPrefix.get() + node.getAttribute("id"));
} else {
_pdf.restoreGraphicsState();
}
};
 
// the actual svgToPdf function (see above)
var svg2pdf = function (element, pdf, options) {
_pdf = pdf;
 
var k = options.scale || 1.0,
xOffset = options.xOffset || 0.0,
yOffset = options.yOffset || 0.0;
 
// set offsets and scale everything by k
_pdf.saveGraphicsState();
_pdf.setCurrentTransformationMatrix(new _pdf.Matrix(k, 0, 0, k, xOffset, yOffset));
 
renderNode(element.cloneNode(true), _pdf.unitMatrix, {}, new SvgPrefix(""), false);
 
_pdf.restoreGraphicsState();
 
return _pdf;
};
 
if (typeof define === "function" && define.amd) {
define(["./rgbcolor", "SvgPath"], function (rgbcolor, svgpath) {
RGBColor = rgbcolor;
SvgPath = svgpath;
return svg2pdf;
});
} else if (typeof module !== "undefined" && module.exports) {
RGBColor = require("./rgbcolor.js");
SvgPath = require("SvgPath");
module.exports = svg2pdf;
} else {
SvgPath = global.SvgPath;
RGBColor = global.RGBColor;
global.svg2pdf = svg2pdf;
// for compatibility reasons
global.svgElementToPdf = svg2pdf;
}
return svg2pdf;
}(typeof self !== "undefined" && self || typeof window !== "undefined" && window || this));
 
},{"./rgbcolor.js":8,"SvgPath":1}]},{},[9])(9)
});
//# sourceMappingURL=svg2pdf.js.map